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;
}

}

OpenGL 5: Shader画心形

时间: 2024-10-13 10:37:12

OpenGL 5: Shader画心形的相关文章

【OpenGL】Shader实例分析(七)- 雪花飘落效果

转发请保持地址:http://blog.csdn.net/stalendp/article/details/40624603 研究了一个雪花飘落效果.感觉挺不错的.分享给大家,效果例如以下: 代码例如以下: Shader "shadertoy/Flakes" { // https://www.shadertoy.com/view/4d2Xzc Properties{ iMouse ("Mouse Pos", Vector) = (100,100,0,0) iChan

【OpenGL】Shader实例分析(六)- 卡牌特效

转发请保持地址:http://blog.csdn.net/stalendp/article/details/30989295 本文将介绍怎么通过alpha通道来隐藏信息,并实现卡牌特效.运行效果如下: 代码如下: Shader "stalendp/imageShine" { Properties { _MainTex ("image", 2D) = "white" {} _NoiseTex("noise", 2D) = &qu

Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3)

Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3) 到上一篇为止,拾取一个VBO里的单个图元的问题已经彻底解决了.那么来看下一个问题:一个场景里可能会有多个VBO,此时每个VBO的gl_VertexID都是从0开始的,那么如何区分不同VBO里的图元呢? 指定起始编号 其实办法很简单.举个例子,士兵站成一排进行报数,那么每个士兵所报的数值都不同:这时又来了一排士兵,需要两排都进行报数,且每个士兵所报的数值都不同,怎么办?让第二排士兵从第一排所报的最后一个数值后面接着报就

Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(2)

Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(2) 上一篇里介绍了Color-Coded Picking的思路和最基本的实现.在处理GL_POINTS时已经没有问题,但是处理GL_LINES.GL_TRIANGLES等时会遇到同一图元的各个顶点颜色不同的问题,这就不能正确拾取了,本问来解决这个问题. 对于GL_LINES,可以用 int objectID = gl_VertexID / 2; 来使得每个线段图元的两个顶点颜色分别相同:对于GL_TRIANGLES,则用

Modern OpenGL用Shader拾取VBO内单一图元的思路和实现

Modern OpenGL用Shader拾取VBO内单一图元的思路和实现 什么意思? 拾取 最简单的理解拾取的方式大概是到(http://www.yakergong.net/nehe/course/tutorial_32.html)玩一下NEHE的拾取游戏.用鼠标点击飞过屏幕的物体就会击中它,这就是拾取的意义. Legacy OpenGL VS Modern OpenGL Legacy OpenGL就是使用glTranslate.glRotate.glScale.gluLookAt.glPers

【OpenGL】Shader实例分析(九)- AngryBots中的主角受伤特效

转发请保持地址:http://blog.csdn.net/stalendp/article/details/40859441 AngryBots是Unity官方的一个非常棒的样例.非常有研究价值. 曾经研究的时候.因为其内容丰富,一时间不知道从哪入手写文章分析. 这一段时间研究shader技术比較多一些,就从shader的这一方面開始吧.首先分析当中的一个屏幕特效:当主角受到攻击时会出现的全屏效果(postScreenEffect).效果例如以下: 事实上这是一种的Bloom效果,相关文件有:M

OpenGL 各个shader的作用和区别

penGL4.0发布了Tessellation shader(Control + Evaluation shader).到OpenGL4.* 为止,现在OpenGL已经支持了5种不同类型的shader. 1.Vertex Shader,简称VS 2.TESS  Control  Shader (D3D11 叫Hull shader),简称TCS 3.TESS Evaluation Shader (D3D叫Domain shader),简称TES 4.Geometry Shader ,简称GS 5

OpenGL中shader使用

引自:http://blog.csdn.net/wl_soft50/article/details/7916720 http://blog.sina.com.cn/s/blog_923fdd9b0102vbe0.html 与OpenGL ES1.x渲染管线相比,OpenGL ES 2.0渲染管线中“顶点着色器”取代了OpenGL ES 1.x渲染管线中的“变换和光照”:“片元着色器”取代了OpenGL ES 1.x渲染管线中的“纹理环境和颜色求和”.“雾”以及“Alpha测试”. 这使得开发人员

【Modern OpenGL】Shader【转】

转自:https://blog.csdn.net/SUKHOI27SMK/article/details/81040161 Shaders 正如在上一篇教程中提到的,shader是在GPU中运行的小程序.如上一个教程中实现的最简单的vertex shader和fragment shader,一个shader基本上负责图形渲染流水线中的一个阶段的功能.从根本上来说,shader就是将输入转化成输出的操作.而且,它们之间是独立的,除了以输入和输出方式外,他们之间不允许进行通信. 上一篇教程中我们仅仅