想系统的学习一下 opengles 就买了一本书《OpenglES 3.0 编程指南》。书中的例子支持在 Windows Linux 安卓等平台运行。因为我的日常开发环境是 Windows ,所以更倾向于在 Windows 上学习,最后再统一移植到安卓。
书上在 Windows 上编译采用的是高通的 Adreno SDK 。然后统一用的 cmake 来编译。我下载的 cmake 和 Adreno SDK 都是最新版的,然后按照书上的操作没有编译成功。就手动的用 vs 的命令行编译环境编译,但是允许时会提示无法加载 egl 的某个 API 虽然不影响最终的结果,还是不爽。网上搜索了,也没有好的办法。于是想用 mingw32 来作为开发环境。
之所以会选择 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 如下。
hello_triangle:
gcc chapter2/$@/$@.c -o bin/$@ -g -lfreeglut -lglew32.dll -lopengl32
clean:
rm bin/*.exe
PS:若是发现在笔记本上不能运行,记得把显卡设置成使用独立显卡,现在的好多笔记本都是双显卡,默认用的集显,改成默认用独显。
问题:
- glCompileShader 函数编译 shader 时是如何支持 opengles 的 shader 语法的,毕竟这是 PC 上用的 GPU 。