初始化Open Program的四个函数:
GLuint shaderProgram = glCreateProgram(); glLinkProgram(shaderProgram); glValidateProgram(shaderProgram); glUseProgram(shaderProgram);
这样创建并使用了一个Open GL Program ,这里是用来装 GL shader的,所以要把shader附加到Program上去, 也需要四个函数:
GLuint shaderObj = glCreateShader(shaderType); glShaderSource(shaderObj, 1, &pTxt, &texLen); glCompileShader(shaderObj); glAttachShader(shaderProgram, shaderObj);
就是这八个函数初始化好shader的。其实看名字就知道大概是干嘛的了。
shader的文本是放在硬盘的text文本,当然什么格式是程序员定义的,也可以是加密的。
只要对C或者C++熟悉,就知道如何把文本shader读入内存操作, 让OpenGL编译并连接shader,比如,我这里自己写的操作函数如下:
void getShaderBuffer(const char *fileName, string &buffer) { FILE *fp; fopen_s(&fp, fileName, "r"); if (!fp) { fprintf(stderr, "Error open file %s fail\n", pVSFileName); exit(1); } char c; while ((c = getc(fp)) != EOF) { buffer.push_back(c); } fclose(fp); }
这里是c和C++的混合操作了,当然也可以直接使用C++的ifstream来做。
总体程序还是挺长的,贴出来参考下吧, 源文件提供下载:http://download.csdn.net/detail/kenden23/7413215
效果如下:
#pragma once #include <stdio.h> #include <GL\glew.h> #include <GL\freeglut.h> #include "math_3d.h" #include <string> #include <iostream> using namespace std; namespace Shader_Begin_4_1 { GLuint VBO; const static float PI = 3.1415926f; int gSegments; const char* pVSFileName = "shader.vs"; const char* pFSFileName = "shader.fs"; static void renderScene() { glClear(GL_COLOR_BUFFER_BIT); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, VBO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glDrawArrays(GL_POLYGON, 0, gSegments); glDisableVertexAttribArray(0); glutSwapBuffers(); } static void initCallBackFunc() { glutDisplayFunc(renderScene); } void genHeart_2(Vector3f *vers, int offset, int segments, float ox, float oy, float R = 0.05) { for (int i = 0; i < segments; i++) { float theta = 2.0f * PI * float(i) / float(segments); float x = R * 16 * pow(sin(theta), 3); float y = R * (13 * cos(theta) - 5*cos(2*theta) - 2*cos(3*theta) - cos(4*theta)); vers[offset+i] = Vector3f(ox+x, oy+y, 0.0f); } } void setupGeoAndBuffer() { const int segments = 360; Vector3f vers[segments]; gSegments = segments; genHeart_2(vers, 0, segments, 0.f, 0.f, 0.1f); glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vers), vers, GL_STATIC_DRAW); } static void attachShader(GLuint shaderProgram, const char *pShaderTxt, GLenum shaderType, int offset, int texLen) { GLuint shaderObj = glCreateShader(shaderType); if (!shaderObj) { fprintf(stderr, "Error create shader type %d\n", shaderType); exit(1); } const char *pTxt = pShaderTxt + offset; glShaderSource(shaderObj, 1, &pTxt, &texLen); glCompileShader(shaderObj); GLint res; glGetShaderiv(shaderObj, GL_COMPILE_STATUS, &res); if (!res) { GLchar infoLog[1024]; glGetShaderInfoLog(shaderObj, sizeof(infoLog), NULL, infoLog); fprintf(stderr, "Error, compile shader type %d\n %s \n", shaderType, infoLog); exit(2); } glAttachShader(shaderProgram, shaderObj); } void getShaderBuffer(const char *fileName, string &buffer) { FILE *fp; fopen_s(&fp, fileName, "r"); if (!fp) { fprintf(stderr, "Error open file %s fail\n", pVSFileName); exit(1); } char c; while ((c = getc(fp)) != EOF) { buffer.push_back(c); } fclose(fp); } static void compileShader() { GLuint shaderProgram = glCreateProgram(); if (!shaderProgram) { fprintf(stderr, "Error create program\n"); exit(1); } int size; string vsBuffer; getShaderBuffer(pVSFileName, vsBuffer); size = vsBuffer.size(); attachShader(shaderProgram, vsBuffer.c_str(), GL_VERTEX_SHADER, 0, size); vsBuffer.clear(); string psBuffer; getShaderBuffer(pFSFileName, psBuffer); size = psBuffer.size(); attachShader(shaderProgram, psBuffer.c_str(), GL_FRAGMENT_SHADER, 0, size); psBuffer.clear(); GLint res = 0; GLchar errorLog[1024] = {0}; glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &res); if (!res) { glGetProgramInfoLog(shaderProgram, sizeof(errorLog), NULL, errorLog); fprintf(stderr, "Error create program %s\n", errorLog); exit(3); } glValidateProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_VALIDATE_STATUS, &res); if (!res) { glGetProgramInfoLog(shaderProgram, sizeof(errorLog), NULL, errorLog); fprintf(stderr, "Error validate program %s\n", errorLog); exit(1); } glUseProgram(shaderProgram); } int run(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(50, 50); glutInitWindowSize(600, 600); glutCreateWindow("Bill's Heart Program"); initCallBackFunc(); GLenum res = glewInit(); if (res != GLEW_OK) { fprintf(stderr, "GLEW init failed \n %s\n", glewGetErrorString(res)); exit(1); } printf("GL version is:\n%s\n", glGetString(GL_VERSION)); glClearColor(0.0f, 0.6f, 0.5f, 0.0f); setupGeoAndBuffer(); compileShader(); glutMainLoop(); return 0; } }
OpenGL 5: Shader画心形
时间: 2024-10-13 10:37:12