OpenGL ES 2.0编程指导阅读笔记(四)一个简单例子

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include "esUtil.h"
#include "esUtil_win.h"

typedef struct
{
	GLfloat *vertices;
	GLfloat *speed;
} UserData;

typedef struct
{
	GLfloat x;
	GLfloat y;
	GLfloat z;
} Coord;

typedef struct
{
	Coord lb;
	Coord lt;
	Coord rb;
	Coord rt;
} Square;

EGLBoolean egl_init(ESContext *esContext, unsigned int width, unsigned int height, UserData *userData)
{

	esInitContext(esContext);

	esContext->width = width;
	esContext->height = height;

	esContext->userData = userData;

	// Get Display
	printf("建立到EGL Display Server的连接...\n");
	esContext->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	if (esContext->eglDisplay == EGL_NO_DISPLAY)
	{
		return EGL_FALSE;
	}

	// Initialize EGL
	printf("初始化EGL...\n");
	if (!eglInitialize(esContext->eglDisplay, NULL, NULL))
	{
		return EGL_FALSE;
	}

	// Get configs
	EGLint numConfigs;
	printf("获取Display可用配置数量...\n");
	if (!eglGetConfigs(esContext->eglDisplay, NULL, 0, &numConfigs))
	{
		return EGL_FALSE;
	}
	else
	{
		printf("Display总计支持配置%d种\n", numConfigs);
	}

	/* EGL Configuration */
	printf("选择RGB模式的2D配置...\n");
	EGLint attribList[] =
		{
			EGL_RED_SIZE, 8,
			EGL_GREEN_SIZE, 8,
			EGL_BLUE_SIZE, 8,
			EGL_ALPHA_SIZE, EGL_DONT_CARE,
			EGL_DEPTH_SIZE, EGL_DONT_CARE,
			EGL_STENCIL_SIZE, EGL_DONT_CARE,
			EGL_SAMPLE_BUFFERS, 0,
			EGL_NONE};

	// Choose config
	EGLConfig config;
	if (!eglChooseConfig(esContext->eglDisplay, attribList, &config, 1, &numConfigs))
	{
		return EGL_FALSE;
	}

	// Show config
	printf("最终选择的配置如下:\n");
	EGLint params;
	eglGetConfigAttrib(esContext->eglDisplay, config, EGL_CONFIG_ID, &params);
	printf("    ID: %d\n", params);
	eglGetConfigAttrib(esContext->eglDisplay, config, EGL_RENDERABLE_TYPE, &params);
	printf("    RENDERABLE TYPE: %d\n", params);
	eglGetConfigAttrib(esContext->eglDisplay, config, EGL_SURFACE_TYPE, &params);
	printf("    SURFACE TYPE: %d\n", params);

	/* Create a window */
	printf("创建窗口...\n");
	if (!WinCreate(esContext, "Hello Triangle"))
	{
		return GL_FALSE;
	}

	// Create a surface
	printf("创建Surface...\n");
	esContext->eglSurface = eglCreateWindowSurface(esContext->eglDisplay, config, (EGLNativeWindowType)esContext->hWnd, NULL);
	if (esContext->eglSurface == EGL_NO_SURFACE)
	{
		return EGL_FALSE;
	}

	// Create a GL context
	printf("创建Context...\n");
	EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE};
	esContext->eglContext = eglCreateContext(esContext->eglDisplay, config, EGL_NO_CONTEXT, contextAttribs);
	if (esContext->eglContext == EGL_NO_CONTEXT)
	{
		return EGL_FALSE;
	}

	// Make the context current
	printf("激活Context...\n");
	if (!eglMakeCurrent(esContext->eglDisplay, esContext->eglSurface, esContext->eglSurface, esContext->eglContext))
	{
		return EGL_FALSE;
	}
}

int load_program()
{
	GLbyte vShaderStr[] =
		"attribute vec4 vPosition;                        \n"
		"uniform vec4 offset;                             \n"
		"void main()                                      \n"
		"{                                                \n"
		"    gl_Position = vPosition + offset;            \n"
		"}                                                \n";

	GLbyte fShaderStr[] =
		"precision mediump float;                         \n"
		"void main()                                      \n"
		"{                                                \n"
		"  gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );    \n"
		"}                                                \n";

	/* Load the vertex shader */
	GLuint vertex_shader;

	// Create the shader object
	printf("创建vertex shader...\n");
	vertex_shader = glCreateShader(GL_VERTEX_SHADER);
	if (vertex_shader == 0)
	{
		printf("%x\n", eglGetError());
		return FALSE;
	}

	// Load the shader source
	printf("加载vertex shader源代码...\n");
	char *vptr = vShaderStr;
	glShaderSource(vertex_shader, 1, &vptr, NULL);

	// Compile the shader
	printf("编译vertex shader...\n");
	glCompileShader(vertex_shader);

	// Check the compile status
	printf("获取vertex shader状态...\n");
	GLint compiled;
	glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &compiled);

	if (!compiled)
	{
		printf("编译失败,获取vertex shader编译信息...\n");
		GLint infoLen = 0;
		glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &infoLen);

		if (infoLen > 1)
		{
			char *infoLog = malloc(sizeof(char) * infoLen);
			glGetShaderInfoLog(vertex_shader, infoLen, NULL, infoLog);
			esLogMessage("Error compiling vertex shader:\n%s\n", infoLog);
			free(infoLog);
		}

		glDeleteShader(vertex_shader);
		return FALSE;
	}
	printf("编译成功...\n");

	/* Load the fragment shader */
	GLuint fragment_shader;

	// Create the shader object
	printf("创建fragment shader...\n");
	fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
	if (fragment_shader == 0)
		return FALSE;

	// Load the shader source
	printf("加载fragment shader源代码...\n");
	char *fptr = fShaderStr;
	glShaderSource(fragment_shader, 1, &fptr, NULL);

	// Compile the shader
	printf("编译fragment shader...\n");
	glCompileShader(fragment_shader);

	// Check the compile status
	printf("获取fragment shader状态...\n");
	glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &compiled);

	if (!compiled)
	{
		printf("编译失败,获取fragment shader编译信息...\n");
		GLint infoLen = 0;
		glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &infoLen);

		if (infoLen > 1)
		{
			char *infoLog = malloc(sizeof(char) * infoLen);
			glGetShaderInfoLog(fragment_shader, infoLen, NULL, infoLog);
			esLogMessage("Error compiling fragment shader:\n%s\n", infoLog);
			free(infoLog);
		}

		glDeleteShader(fragment_shader);
		return FALSE;
	}
	printf("编译成功...\n");

	glReleaseShaderCompiler();

	GLuint programObject;
	GLint linked;
	// Create the program object
	printf("创建program...\n");
	programObject = glCreateProgram();

	if (programObject == 0)
	{
		return FALSE;
	}

	printf("附加shader...\n");
	glAttachShader(programObject, vertex_shader);
	glAttachShader(programObject, fragment_shader);

	// Bind vPosition to attribute 1
	printf("绑定attribute location...\n");
	glBindAttribLocation(programObject, 1, "vPosition");

	// Link the program
	printf("链接程序...\n");
	glLinkProgram(programObject);

	// Check the link status
	printf("获取program状态...\n");
	glGetProgramiv(programObject, GL_LINK_STATUS, &linked);

	if (!linked)
	{
		printf("链接失败,获取program链接信息...\n");
		GLint infoLen = 0;

		glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);

		if (infoLen > 1)
		{
			char *infoLog = malloc(sizeof(char) * infoLen);

			glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
			esLogMessage("Error linking program:\n%s\n", infoLog);

			free(infoLog);
		}

		printf("删除program...\n");
		glDeleteProgram(programObject);
		return FALSE;
	}
	printf("链接成功...\n");

	/* Show program information */
	printf("Program信息:\n");
	GLuint num;
	glGetProgramiv(programObject, GL_ACTIVE_UNIFORMS, &num);
	printf("    Uniform数量: %d\n", num);
	GLsizei max_length;
	glGetProgramiv(programObject, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_length);
	char *name;
	name = malloc(max_length);
	GLint size;
	GLint type;
	for (int i = 0; i < num; i++)
	{
		GLint loc;
		glGetActiveUniform(programObject, i, max_length, NULL, &size, &type, name);
		loc = glGetUniformLocation(programObject, name);
		printf("        ID %d: <%d> %s[%d] (%x)\n", i, loc, name, size, type);
	}
	free(name);
	glGetProgramiv(programObject, GL_ACTIVE_ATTRIBUTES, &num);
	printf("    Attribute数量: %d\n", num);
	glGetProgramiv(programObject, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_length);
	name = malloc(max_length);
	for (int i = 0; i < num; i++)
	{
		GLint loc;
		glGetActiveAttrib(programObject, i, max_length, NULL, &size, &type, name);
		loc = glGetAttribLocation(programObject, name);
		printf("        ID %d: <%d> %s[%d] (%x)\n", i, loc, name, size, type);
	}
	free(name);

	printf("使用program...\n");
	glUseProgram(programObject);

	return TRUE;
}

void updateFunc(ESContext *esContext, float deltaTime)
{
	UserData *userData = esContext->userData;
	Square *square = userData->vertices;
	Coord *speed = userData->speed;

	GLfloat width = square->rb.x - square->lb.x;
	GLfloat height = square->lt.y - square->lb.y;

	square->lb.x += deltaTime * speed->x;
	if (square->lb.x <= -1.0)
	{
		square->lb.x = -2.0 - square->lb.x;
		speed->x = -speed->x;
	}
	else if (square->lb.x + width >= 1.0)
	{
		square->lb.x = 2.0 - 2 * width - square->lb.x;
		speed->x = -speed->x;
	}
	square->lt.x = square->lb.x;
	square->rb.x = square->lb.x + width;
	square->rt.x = square->rb.x;

	square->lb.y += deltaTime * speed->y;
	if (square->lb.y <= -1.0)
	{
		square->lb.y = -2.0 - square->lb.y;
		speed->y = -speed->y;
	}
	else if (square->lb.y + height >= 1.0)
	{
		square->lb.y = 2.0 - 2 * height - square->lb.y;
		speed->y = -speed->y;
	}
	square->rb.y = square->lb.y;
	square->lt.y = square->lb.y + height;
	square->rt.y = square->lt.y;
}

void Draw(ESContext *esContext)
{
	UserData *userData = esContext->userData;
	GLfloat *vVertices = userData->vertices;

	// Set the viewport
	glViewport(0, 0, esContext->width, esContext->height);

	// Clear the color buffer
	glClear(GL_COLOR_BUFFER_BIT);

	// Load the vertex data
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
	glEnableVertexAttribArray(1);

	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	// glDrawArrays(GL_TRIANGLES, 0, 6);

	eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}

int main(int argc, char *argv[])
{
	/* Initialize esContext */
	ESContext esContext;
	UserData userData;

	// UserData
	GLfloat vVertices[] = {0.0f, 0.0f, 0.0f,
						   0.0f, 0.05f, 0.0f,
						   0.05f, 0.0f, 0.0f,
						   0.05f, 0.05f, 0.0f};

	userData.vertices = vVertices;

	GLfloat speed[] = {0.4f, 0.1f, 0.0f};

	userData.speed = speed;

	if (!egl_init(&esContext, 800, 800, &userData))
	{
		printf("初始化EGL失败...\n");
		return -1;
	}

	/* load shader source & compile & link */
	if (!load_program())
	{
		printf("加载程序失败...\n");
		return -2;
	}

	/* global graphical configuration */
	printf("设置背景色...\n");
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	// Set uniform
	glUniform4f(0, -0.025f, -0.025f, 0.0f, 0.0f);

	/* assign draw function */
	printf("指定绘图程序...\n");
	esContext.drawFunc = Draw;
	esContext.updateFunc = updateFunc;

	/* start drawing */
	printf("开始绘图...\n");
	MSG msg = {0};
	int done = 0;
	DWORD lastTime = GetTickCount64();

	while (!done)
	{
		int gotMsg = (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0);
		DWORD curTime = GetTickCount64();
		float deltaTime = (float)(curTime - lastTime) / 1000.0f;
		if (deltaTime < 0.00833f)
		{
			Sleep(1);
			continue;
		}
		lastTime = curTime;

		if (gotMsg)
		{
			if (msg.message == WM_QUIT)
			{
				done = 1;
			}
			else
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else
			SendMessage(esContext.hWnd, WM_PAINT, 0, 0);

		// Call update function if registered
		if (esContext.updateFunc != NULL)
			esContext.updateFunc(&esContext, deltaTime);
	}
	return 0;
}
posted @ 2023-01-13 16:15  xvsay  阅读(152)  评论(0)    收藏  举报