首页 > 代码库 > OpenGL 5: Shader画心形

OpenGL 5: Shader画心形

初始化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;
}

}