您尚未登录。

楼主 #1 2021-01-18 17:06:35

拉轰的脚踏车
会员
注册时间: 2020-03-20
已发帖子: 288
积分: 222

试一试 直接用 win32 api 运行 OpenGL 程序

/* 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

离线

楼主 #2 2021-01-18 17:08:09

拉轰的脚踏车
会员
注册时间: 2020-03-20
已发帖子: 288
积分: 222

Re: 试一试 直接用 win32 api 运行 OpenGL 程序

2021-01-18_170659.png

按住 CTRL 键, 可以平移和缩放。

离线

#3 2021-01-18 18:53:48

armstrong
会员
注册时间: 2019-04-10
已发帖子: 269
积分: 183.5

Re: 试一试 直接用 win32 api 运行 OpenGL 程序

搬出我多年前的收藏给楼主助威吧,NEHE OpenGL 教学例程,例程个个精美:
nehegl.zip

最近编辑记录 armstrong (2021-01-18 18:55:44)

离线

楼主 #4 2021-01-18 20:25:26

拉轰的脚踏车
会员
注册时间: 2020-03-20
已发帖子: 288
积分: 222

Re: 试一试 直接用 win32 api 运行 OpenGL 程序

armstrong 说:

搬出我多年前的收藏给楼主助威吧,NEHE OpenGL 教学例程,例程个个精美:
nehegl.zip

大哥! 太强大了!

整整48个例程啊, 我直接用VC2017编译了最后一个例程, 改了两三行就编译运行了, 真不依赖任何第三方库.

顺便请教一个问题, 现在我们公司的软件有点变态, 里面最多可能有一百万条线段的连接, OpenGL渲染可能要好几十微秒,

这种情况下鼠标还要能继续画线, 如果一起渲染的画感觉有点卡了,

请问OpenGL有没有增量渲染呢?或者说局部渲染? 这样感觉可以提高流畅度.

离线

#5 2021-01-18 23:47:18

落日余晖
会员
注册时间: 2019-11-23
已发帖子: 34
积分: 26.5

Re: 试一试 直接用 win32 api 运行 OpenGL 程序

armstrong 说:

搬出我多年前的收藏给楼主助威吧,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的人认为自己是精英,对共享知识没有兴趣。非常令人沮丧!

看到这里, 感觉作者就像天使一样.

离线

#6 2024-07-04 11:45:20

memory
会员
注册时间: 2021-08-11
已发帖子: 325
积分: 301

Re: 试一试 直接用 win32 api 运行 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

QQ截图20240704114840.png

离线

#7 2024-07-04 17:31:24

memory
会员
注册时间: 2021-08-11
已发帖子: 325
积分: 301

Re: 试一试 直接用 win32 api 运行 OpenGL 程序

QQ截图20240704173002.png

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

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn