/* An example of an OpenGL animation loop using the Win32 API. Also
demonstrates palette management for RGB and color index modes and
general strategies for message handling. */
#include <windows.h> /* must include this before GL/gl.h */
#include <windowsx.h>
#include <GL/gl.h> /* OpenGL header file */
#include <stdio.h>
#pragma comment(lib, "opengl32.lib")
HDC hDC; /* device context */
HPALETTE hPalette = 0; /* custom palette (if needed) */
GLboolean animate = GL_TRUE; /* animation flag */
#define IDT_TIMER1 1000
float fZoom = 1.0f;
POINT m_lastPos = {0, 0};
float m_xMove;
float m_yMove;
bool in_drag = false;//是否处于拖动模式
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glClearColor(1, 1, 1, 1);
glScalef(fZoom, fZoom, 0);
glTranslatef(m_xMove, m_yMove, -10.0);
/*
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glColor3f(0.2, 0.2, 0.5);
glVertex3f(0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glEnd();
*/
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glColor3f(0.2f, 0.2f, 0.5f);
glVertex3f(-0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glEnd();
glFlush();
SwapBuffers(hDC); /* nop if singlebuffered */
}
LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static PAINTSTRUCT ps;
int delta = 0;
char strLog[64];
switch (uMsg) {
case WM_CREATE:
//SetTimer(hWnd, IDT_TIMER1, 1, NULL);
break;
case WM_PAINT:
BeginPaint(hWnd, &ps);
display();
EndPaint(hWnd, &ps);
return 0;
case WM_TIMER:
switch (wParam)
{
case IDT_TIMER1:
PostMessage(hWnd, WM_PAINT, 0, 0);
return 0;
}
break;
case WM_MOUSEWHEEL:
if ((wParam & MK_CONTROL) == MK_CONTROL)
{
delta += (short)HIWORD(wParam); // 120 or -120
if (delta >= 120)
{
fZoom += 0.03f;
}
else if (delta <= -120)
{
fZoom -= 0.03f;
}
if (fZoom < 0.00001f)
fZoom = 0.01f;
}
if (HIBYTE(GetKeyState(VK_MENU)) & 0x80)
{
OutputDebugString("alt is press\n");
}
// PostMessage(hWnd, WM_PAINT, 0, 0);
SendMessage(hWnd, WM_PAINT, 0, 0);
snprintf(strLog, sizeof(strLog), "%f\n", fZoom);
OutputDebugString(strLog);
break;
case WM_MBUTTONUP:
break;
case WM_LBUTTONDOWN:
if ((wParam & MK_CONTROL) == MK_CONTROL)
{
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
snprintf(strLog, sizeof(strLog), "press: %d,%d\n", pt.x, pt.y);
OutputDebugString(strLog);
m_lastPos = pt;
in_drag = true;
}
break;
case WM_LBUTTONUP:
POINT pt2;
pt2.x = GET_X_LPARAM(lParam);
pt2.y = GET_Y_LPARAM(lParam);
snprintf(strLog, sizeof(strLog), "release: %d,%d\n", pt2.x, pt2.y);
OutputDebugString(strLog);
in_drag = false;
break;
case WM_MOUSEMOVE:
if (((wParam & MK_CONTROL) == MK_CONTROL) && in_drag)
{
POINT pt3;
int dx, dy;
float dx_scale, dy_scale;
pt3.x = GET_X_LPARAM(lParam);
pt3.y = GET_Y_LPARAM(lParam);
snprintf(strLog, sizeof(strLog), "move: %d,%d\n", pt3.x, pt3.y);
OutputDebugString(strLog);
dx = pt3.x - m_lastPos.x;
dy = pt3.y - m_lastPos.y;
dx_scale = dx * (1 / (float)800);
dy_scale = -dy * (1 / (float)640);
m_xMove = m_xMove + dx_scale;
m_yMove = m_yMove + dy_scale;
m_lastPos = pt3;
SendMessage(hWnd, WM_PAINT, 0, 0);
}
break;
case WM_SIZE:
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
PostMessage(hWnd, WM_PAINT, 0, 0);
return 0;
case WM_CHAR:
switch (wParam) {
case 27: /* ESC key */
PostQuitMessage(0);
break;
case ' ':
animate = !animate;
break;
}
return 0;
#if 0
case WM_ACTIVATE:
if (IsIconic(hWnd))
animate = GL_FALSE;
else
animate = GL_TRUE;
return 0;
#endif
case WM_PALETTECHANGED:
if (hWnd == (HWND)wParam)
break;
/* fall through to WM_QUERYNEWPALETTE */
case WM_QUERYNEWPALETTE:
if (hPalette) {
UnrealizeObject(hPalette);
SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
return TRUE;
}
return FALSE;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
HWND CreateOpenGLWindow(char* title, int x, int y, int width, int height,
BYTE type, DWORD flags)
{
int n, pf;
HWND hWnd;
WNDCLASS wc;
LOGPALETTE* lpPal;
PIXELFORMATDESCRIPTOR pfd;
static HINSTANCE hInstance = 0;
/* only register the window class once - use hInstance as a flag. */
if (!hInstance) {
hInstance = GetModuleHandle(NULL);
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";
if (!RegisterClass(&wc)) {
MessageBox(NULL, "RegisterClass() failed: "
"Cannot register window class.", "Error", MB_OK);
return NULL;
}
}
hWnd = CreateWindow("OpenGL", title, WS_OVERLAPPEDWINDOW |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
x, y, width, height, NULL, NULL, hInstance, NULL);
if (hWnd == NULL) {
MessageBox(NULL, "CreateWindow() failed: Cannot create a window.",
"Error", MB_OK);
return NULL;
}
hDC = GetDC(hWnd);
/* there is no guarantee that the contents of the stack that become
the pfd are zeroed, therefore _make sure_ to clear these bits. */
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | flags;
pfd.iPixelType = type;
pfd.cColorBits = 32;
pf = ChoosePixelFormat(hDC, &pfd);
if (pf == 0) {
MessageBox(NULL, "ChoosePixelFormat() failed: "
"Cannot find a suitable pixel format.", "Error", MB_OK);
return 0;
}
if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
MessageBox(NULL, "SetPixelFormat() failed: "
"Cannot set format specified.", "Error", MB_OK);
return 0;
}
DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
if (pfd.dwFlags & PFD_NEED_PALETTE ||
pfd.iPixelType == PFD_TYPE_COLORINDEX) {
n = 1 << pfd.cColorBits;
if (n > 256) n = 256;
lpPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
sizeof(PALETTEENTRY) * n);
memset(lpPal, 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * n);
lpPal->palVersion = 0x300;
lpPal->palNumEntries = n;
GetSystemPaletteEntries(hDC, 0, n, &lpPal->palPalEntry[0]);
/* if the pixel type is RGBA, then we want to make an RGB ramp,
otherwise (color index) set individual colors. */
if (pfd.iPixelType == PFD_TYPE_RGBA) {
int redMask = (1 << pfd.cRedBits) - 1;
int greenMask = (1 << pfd.cGreenBits) - 1;
int blueMask = (1 << pfd.cBlueBits) - 1;
int i;
/* fill in the entries with an RGB color ramp. */
for (i = 0; i < n; ++i) {
lpPal->palPalEntry[i].peRed =
(((i >> pfd.cRedShift) & redMask) * 255) / redMask;
lpPal->palPalEntry[i].peGreen =
(((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
lpPal->palPalEntry[i].peBlue =
(((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
lpPal->palPalEntry[i].peFlags = 0;
}
}
else {
lpPal->palPalEntry[0].peRed = 0;
lpPal->palPalEntry[0].peGreen = 0;
lpPal->palPalEntry[0].peBlue = 0;
lpPal->palPalEntry[0].peFlags = PC_NOCOLLAPSE;
lpPal->palPalEntry[1].peRed = 255;
lpPal->palPalEntry[1].peGreen = 0;
lpPal->palPalEntry[1].peBlue = 0;
lpPal->palPalEntry[1].peFlags = PC_NOCOLLAPSE;
lpPal->palPalEntry[2].peRed = 0;
lpPal->palPalEntry[2].peGreen = 255;
lpPal->palPalEntry[2].peBlue = 0;
lpPal->palPalEntry[2].peFlags = PC_NOCOLLAPSE;
lpPal->palPalEntry[3].peRed = 0;
lpPal->palPalEntry[3].peGreen = 0;
lpPal->palPalEntry[3].peBlue = 255;
lpPal->palPalEntry[3].peFlags = PC_NOCOLLAPSE;
}
hPalette = CreatePalette(lpPal);
if (hPalette) {
SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
}
free(lpPal);
}
ReleaseDC(hWnd, hDC);
return hWnd;
}
int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst,
LPSTR lpszCmdLine, int nCmdShow)
{
HGLRC hRC; /* opengl context */
HWND hWnd; /* window */
MSG msg; /* message */
DWORD buffer = PFD_DOUBLEBUFFER; /* buffering type */
BYTE color = PFD_TYPE_RGBA; /* color type */
if (strstr(lpszCmdLine, "-sb")) {
buffer = 0;
}
if (strstr(lpszCmdLine, "-ci")) {
color = PFD_TYPE_COLORINDEX;
}
if (strstr(lpszCmdLine, "-h")) {
MessageBox(NULL, "animate [-ci] [-sb]\n"
" -sb single buffered\n"
" -ci color index\n",
"Usage help", MB_ICONINFORMATION);
exit(0);
}
hWnd = CreateOpenGLWindow((char*)"opengl test ---- https://whycan.com", 0, 0, 800, 640, color, buffer);
if (hWnd == NULL)
exit(1);
hDC = GetDC(hWnd);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hDC);
wglDeleteContext(hRC);
DestroyWindow(hWnd);
if (hPalette)
DeleteObject(hPalette);
return 0;
}
不依赖任何第三方库, 可执行文件下载: win32_opengl_test_1.7z
离线
按住 CTRL 键, 可以平移和缩放。
离线
搬出我多年前的收藏给楼主助威吧,NEHE OpenGL 教学例程,例程个个精美:
nehegl.zip
最近编辑记录 armstrong (2021-01-18 18:55:44)
离线
搬出我多年前的收藏给楼主助威吧,NEHE OpenGL 教学例程,例程个个精美:
nehegl.zip
大哥! 太强大了!
整整48个例程啊, 我直接用VC2017编译了最后一个例程, 改了两三行就编译运行了, 真不依赖任何第三方库.
顺便请教一个问题, 现在我们公司的软件有点变态, 里面最多可能有一百万条线段的连接, OpenGL渲染可能要好几十微秒,
这种情况下鼠标还要能继续画线, 如果一起渲染的画感觉有点卡了,
请问OpenGL有没有增量渲染呢?或者说局部渲染? 这样感觉可以提高流畅度.
离线
搬出我多年前的收藏给楼主助威吧,NEHE OpenGL 教学例程,例程个个精美:
nehegl.zip
不错, 找到官网了, 就是这个
https://github.com/gamedev-net/nehe-opengl/tree/master/vc
http://nehe.gamedev.net/tutorial/creating_an_opengl_window_(win32)/13001/
欢迎来到我的OpenGL教程。我是一个对OpenGL充满热情的普通人!当3Dfx为Voodoo 1卡发布他们的硬件加速OpenGL驱动程序时,我第一次听说OpenGL。我立刻知道OpenGL是我必须学习的东西。不幸的是,很难在书籍或网上找到有关OpenGL的任何信息。我花了数小时试图使代码正常工作,甚至花更多时间恳求人们在电子邮件和IRC上寻求帮助。我发现那些了解OpenGL的人认为自己是精英,对共享知识没有兴趣。非常令人沮丧!
看到这里, 感觉作者就像天使一样.
离线
准备工作:
sudo apt-get install libsdl2-*-dev
#include <stdio.h>
#include <stdbool.h>
#include <SDL.h>
#include <SDL_opengles2.h> // 注意这里使用的是ES2的头文件,如果你的系统支持,可以使用<SDL_opengl.h>代替
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n"
"\0";
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Simple SDL2 OpenGL Demo",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
800, 600,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
SDL_GLContext context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, context);
// Request an OpenGL 3.3 context
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(vertexShader);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "FragColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (true)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))
exit(0);
}
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
编译指令:
gcc -o test test.c `sdl2-config --cflags --libs` `pkg-config --cflags --libs sdl2_image` -lGL
离线
https://github.com/it-elektronika/SDL_RANDOM/blob/master/SDL_RenderCopy.c
#include "SDL2/SDL.h"
#define SHAPE_SIZE 64
int main(int argc, char *argv[])
{
SDL_Window* Main_Window;
SDL_Renderer* Main_Renderer;
SDL_Surface* Loading_Surf;
SDL_Texture* Background_Tx;
SDL_Texture* BlueShapes;
/* Rectangles for drawing which will specify source (inside the texture)
and atarget (on the screen) for rendering our textures. */
SDL_Rect SrcR;
SDL_Rect DestR;
SrcR.x = 0;
SrcR.y = 0;
SrcR.w = SHAPE_SIZE;
SrcR.h = SHAPE_SIZE;
DestR.x = 640 / 2 - SHAPE_SIZE / 2;
DestR.y = 580 / 2 - SHAPE_SIZE / 2;
DestR.w = SHAPE_SIZE;
DestR.h = SHAPE_SIZE;
/* Before we can render anything, we need a window and a renderer */
Main_Window = SDL_CreateWindow("SDL_RenderCopy Example",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 580, 0);
Main_Renderer = SDL_CreateRenderer(Main_Window, -1, SDL_RENDERER_SOFTWARE);
/* The loading of the background texture. Since SDL_LoadBMP() returns
a surface, we convert it to a texture afterwards for fast accelerated
blitting. */
Loading_Surf = SDL_LoadBMP("red.bmp");
Background_Tx = SDL_CreateTextureFromSurface(Main_Renderer, Loading_Surf);
SDL_FreeSurface(Loading_Surf); /* we got the texture now -> free surface */
/* Load an additional texture */
Loading_Surf = SDL_LoadBMP("green.bmp");
BlueShapes = SDL_CreateTextureFromSurface(Main_Renderer, Loading_Surf);
SDL_FreeSurface(Loading_Surf);
/* now onto the fun part.
This will render a rotating selection of the blue shapes
in the middle of the screen */
int i;
int n;
for (i = 0; i < 2; ++i)
{
for(n = 0; n < 4; ++n)
{
SrcR.x = SHAPE_SIZE * (n % 2);
if (n > 1)
{
SrcR.y = SHAPE_SIZE;
} else
{
SrcR.y = 0;
}
/* render background, whereas NULL for source and destination
rectangles just means "use the default" */
SDL_RenderCopy(Main_Renderer, Background_Tx, NULL, NULL);
/* render the current animation step of our shape */
SDL_RenderCopy(Main_Renderer, BlueShapes, &SrcR, &DestR);
SDL_RenderPresent(Main_Renderer);
SDL_Delay(500);
}
}
/* The renderer works pretty much like a big canvas:
when you RenderCopy() you are adding paint, each time adding it
on top.
You can change how it blends with the stuff that
the new data goes over.
When your 'picture' is complete, you show it
by using SDL_RenderPresent(). */
/* SDL 1.2 hint: If you're stuck on the whole renderer idea coming
from 1.2 surfaces and blitting, think of the renderer as your
main surface, and SDL_RenderCopy() as the blit function to that main
surface, with SDL_RenderPresent() as the old SDL_Flip() function.*/
SDL_DestroyTexture(BlueShapes);
SDL_DestroyTexture(Background_Tx);
SDL_DestroyRenderer(Main_Renderer);
SDL_DestroyWindow(Main_Window);
return 0;
}
编译指令:
gcc -o test2 test2.c `sdl2-config --cflags --libs` `pkg-config --cflags --libs sdl2_image` -lGL
离线