用 glew 來學習 opengles

想系統的學習一下 opengles 就買了一本書《OpenglES 3.0 編程指南》。書中的例子支持在 Windows Linux 安卓等平臺運行。由於個人平常開發環境是 Windows ,因此更傾向於在 Windows 上學習,最後再統一移植到安卓。編程

書上在 Windows 上編譯採用的是高通的 Adreno SDK 。而後統一用的 cmake 來編譯。我下載的 cmake 和 Adreno SDK 都是最新版的,而後按照書上的操做沒有編譯成功。就手動的用 vs 的命令行編譯環境編譯,可是容許時會提示沒法加載 egl 的某個 API 雖然不影響最終的結果,仍是不爽。網上搜索了,也沒有好的辦法。因而想用 mingw32 來做爲開發環境。xcode

之因此會選擇 mingw32 是由於 ejoy2d 就支持用 mingw32 編譯。而後窗口的建立我用的 freeglut 。因而最終用 mingw32 + glew + freeglut 成功運行了第一個實例。具體代碼下所示。函數

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>

#define logv printf

static GLuint _program;

/**
 * 加載並編譯 shader 。
 */
static GLuint 
load_shader(GLenum shadertype, const GLchar *shadercode) {
	GLuint shader = glCreateShader(shadertype);
	if (shader == 0) {
		logv("Fail to create shader\n");
		return 0;
	}

	// 編譯
	glShaderSource(shader, 1, &shadercode, NULL);
	glCompileShader(shader);

	// 檢查編譯結果
	GLint value = 0;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
	if (value == GL_FALSE) {
		value = 0;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
		if (value > 1) {
			GLchar info[value + 1];
			glGetShaderInfoLog(shader, value, NULL, info);
			logv("Fail to compile shader: %s\n", info);
		}
		glDeleteShader(shader);
	}

	return shader;
}

/**
 * 加載 shader 並連接。
 */
static GLuint 
link_programs(GLchar *vertexcode, GLchar *fragmentcode) {
	GLuint vertexshader = 0, fragmentshader = 0, program = 0;
	vertexshader = load_shader(GL_VERTEX_SHADER, vertexcode);
	if (vertexshader == 0) {
		logv("Fail to create vertex shader");
		goto EXIT;
	}
	fragmentshader  = load_shader(GL_FRAGMENT_SHADER, fragmentcode);
	if (fragmentshader == 0) {
		logv("Fail to create fragment shader");
		goto EXIT;
	}

	program = glCreateProgram();
	if (program == 0) {
		logv("Fail to create program");
		goto EXIT;
	}

	// 連接
	glAttachShader(program, vertexshader);
	glAttachShader(program, fragmentshader);
	glLinkProgram(program);

	// 查看連接結果
	GLint value = 0;
	glGetProgramiv(program, GL_LINK_STATUS, &value);
	if (value == GL_FALSE) {
		value = 0;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value);
		if (value > 1) {
			GLchar info[value];
			glGetProgramInfoLog(program, value, NULL, info);
			logv("Fail to link program: %s\n", info);
		}
		goto EXIT;
	}

	return program;
EXIT:
	if (vertexshader != 0)
		glDeleteShader(vertexshader);
	if (fragmentshader != 0)
		glDeleteShader(fragmentshader);
	if (program != 0)
		glDeleteProgram(program);
	return 0;
}

static GLboolean
init() {
	GLenum err = glewInit();
	if (err != GLEW_OK) {
		logv("Fail to init glew\n");
		return GL_FALSE;
	}

	GLchar vertexcode[] =
      "#version 300 es                          \n"
      "layout(location = 0) in vec4 vPosition;  \n"
      "void main()                              \n"
      "{                                        \n"
      "   gl_Position = vPosition;              \n"
      "}                                        \n";

   GLchar fragmentcode[] =
      "#version 300 es                              \n"
      "precision mediump float;                     \n"
      "out vec4 fragColor;                          \n"
      "void main()                                  \n"
      "{                                            \n"
      "   fragColor = vec4 (1.0, 0.0, 0.0, 1.0);    \n"
      "}                                            \n";

    _program = link_programs(vertexcode, fragmentcode);
    if (_program == 0)
    	return GL_FALSE;
    return GL_TRUE;
}

static void
cb_display() {
	logv("cb_display\n");
   	GLfloat vVertices[] = {0.0f, 0.5f, 0.0f,
                           -0.5f, -0.5f, 0.0f,
                           0.5f, -0.5f, 0.0f};

   	glClear(GL_COLOR_BUFFER_BIT);
   	glUseProgram(_program);

   	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
   	glEnableVertexAttribArray(0);

   	glDrawArrays (GL_TRIANGLES, 0, 3);

	glFlush();
}

static void 
cb_reshape(int width, int height) {
	logv("cb_reshape: width:%d, height:%d\n", width, height);
	glViewport (0, 0, width, height);
}

int
main(int argc, char *argv[]) {
	glutInit(&argc, argv);
	glutInitWindowSize(800, 400);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(0, 0);

	glutCreateWindow("OpenGL ES Title");

	if (init() == GL_FALSE)
		return 0;

	glClearColor(0, 0, 0, 1.f);

	glutDisplayFunc(cb_display);
	glutReshapeFunc(cb_reshape);
	glutMainLoop();

	glDeleteProgram(_program);
	return 0;
}

編譯的話下載 glew 本身編譯,freeglut 的話去官網有別人編譯好的 mingw32 的連接,直接用就行了。makefile 以下。oop

hello_triangle:
	gcc chapter2/$@/$@.c -o bin/$@ -g -lfreeglut -lglew32.dll -lopengl32
clean:
	rm bin/*.exe

PS:如果發如今筆記本上不能運行,記得把顯卡設置成使用獨立顯卡,如今的好多筆記本都是雙顯卡,默認用的集顯,改爲默認用獨顯。學習

問題:ui

  • glCompileShader 函數編譯 shader 時是如何支持 opengles 的 shader 語法的,畢竟這是 PC 上用的 GPU 。
相關文章
相關標籤/搜索