我将注解以及源码直接放到这里了
// GLSL01.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <GL/glew.h>
#include <GL/glut.h>
#include <cassert>
using namespace std;
static const int g_timer_id = 0;
static const int g_time_per_frame = 16;//ms
#define OFFSET_MEMBER(s, m) (size_t)&(((s*)0)->m)
//vertex 3 float
//color 3 byte
//texture 2 float
struct VF3_CB3_TF2
{
GLfloat m_vertex[3];
GLubyte m_color[3];
GLfloat m_texture[2];
};
typedef struct _VF3_CB3_TF2_Quad
{
VF3_CB3_TF2 tl;//top left
VF3_CB3_TF2 bl;//bottom left
VF3_CB3_TF2 tr;//top right
VF3_CB3_TF2 br;//bottom right
} VF3_CB3_TF2_Quad;
static GLuint g_program = 0;
static GLuint g_vertex_shader = 0;
static GLuint g_frag_shader = 0;
static GLuint g_texture = 0;
enum
{
eVertex = 0,
eColor,
eTexture,
};
static const char *attrib_vertex_name = "a_vertex";
static const char *attrib_color_name = "a_color";
static const char *attrib_texture_name = "a_texture";
static const GLchar *vertex_source =
"uniform sampler2D texture0;\n"
"attribute vec4 a_vertex;\n"
"attribute vec3 a_color;\n"
"attribute vec2 a_texture;\n"
"varying vec4 v_color;\n"
"varying vec2 v_texture;\n"
"\n"
"void main(void) {\n"
"gl_Position = gl_ModelViewProjectionMatrix * a_vertex; \n"
"v_color = vec4(a_color.r/255.0f, a_color.g/255.0f,a_color.b/255.0f, 1.0f);\n" //没有混合
"v_texture = a_texture;\n"
"}\n"
"//END";
static const GLchar *frag_source =
"uniform sampler2D texture0;\n"
"varying vec4 v_color;\n"
"varying vec2 v_texture;\n"
"\n"
"void main(void){\n"
"\n"
//v_color在这里会增加颜色的混合效果,如果去掉
//或者将其设置为v_color = vec4(1.0f, 1.0f, 1.0f, 1.0f)则
//直接将纹理显示到最后结果
"\n"
"gl_FragColor = v_color * texture2D(texture0,v_texture) ;\n"
"}\n"
"//END";
//---------------------------------------------------------------------------------------------------------------------
void initShader();
void render();
void initQuadWithData(float top, float left, float width,float height, VF3_CB3_TF2_Quad& quad);
void readBitmp24(const std::string& filename, void* &ptr, int &width, int &height, int& totals);
/
void init()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClearDepth(1.0f);
glShadeModel(GL_SMOOTH);
glGenTextures(1, &g_texture);
assert(g_texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//default texture in multi-textrures
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, g_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
void *bmpData = 0;
int width=0, height=0, totals=0;
readBitmp24("e:/test.bmp",bmpData, width, height, totals);
assert(bmpData);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,bmpData);
delete[] bmpData;
bmpData = 0;
glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
assert(glGetError() == GL_NO_ERROR);
}
void readBitmp24(const std::string& filename, void* &ptr, int &width, int &height, int& totals)
{
fstream in(filename.c_str(), ios_base::in|ios_base::binary);
if (!in)
{
ptr = NULL;
return;
}
in.seekg(0x12); //18个字节开始读取宽度和高度
in.read((char*)&width, sizeof(int));
in.read((char*)&height,sizeof(int));
//BMP的每行按照4个字节对齐
int realWidth = width;
int lineLength = width*3;
while (lineLength % 4 != 0)
++lineLength;
totals = lineLength * height;
ptr = new char[totals];
in.seekg(0x36); //54开始是数据,按照行读取
in.read((char*)ptr, totals);
//将BGR模式转换为RGB模式
char *startPos = NULL,*curPos = NULL;
for (int i=0; i<height; ++i)
{
curPos = ((char*)ptr+i*lineLength);
for (int j=0; j<realWidth;++j)
{
std::swap(curPos[0], curPos[2]);
curPos += 3;
}
}
in.close();
}
void initQuadWithData( float top, float left, float width,float height,VF3_CB3_TF2_Quad& quad)
{
memset(&quad, 0, sizeof(VF3_CB3_TF2_Quad));
//坐标
quad.tl.m_vertex[0] = left;
quad.tl.m_vertex[1] = top;
quad.bl.m_vertex[0] = left;
quad.bl.m_vertex[1] = top-height;
quad.tr.m_vertex[0] = left+width;
quad.tr.m_vertex[1] = top;
quad.br.m_vertex[0] = left+width;
quad.br.m_vertex[1] = top-height;
//颜色
static const GLubyte red_color[3] = {255, 0, 0};
static const GLubyte green_color[3] = {0, 255, 0};
static const GLubyte blue_color[3] = {0,0,255};
static const GLubyte white_color[3] = {255,255,255};
memcpy(&quad.tl.m_color,blue_color, sizeof(GLubyte)*3);
// memcpy(&quad.bl.m_color,white_color, sizeof(GLubyte)*3);
// memcpy(&quad.tr.m_color,white_color, sizeof(GLubyte)*3);
memcpy(&quad.br.m_color,red_color, sizeof(GLbyte)*3);
//printf("initialize data...\n");
//纹理
static const GLfloat tl_texture[2] = {0,1};
static const GLfloat bl_texture[2] = {0, 0};
static const GLfloat tr_texture[2] = {1, 1};
static const GLfloat br_texture[2] = {1,0};
memcpy(&quad.tl.m_texture, tl_texture, sizeof(GLfloat)*2);
memcpy(&quad.bl.m_texture, bl_texture, sizeof(GLfloat)*2);
memcpy(&quad.tr.m_texture, tr_texture, sizeof(GLfloat)*2);
memcpy(&quad.br.m_texture, br_texture, sizeof(GLfloat)*2);
}
void render()
{
// glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// //glColor3f(0,0,0.5f);
// glBegin(GL_TRIANGLE_STRIP);
// // glRectf(-.5, .5, .5, -.5);
//
// glColor3f(0,0,1.0f); //blue
// glVertex2f(-0.5, 0.5);
//
// glColor3f(0,0,0);
// glVertex2f(-0.5, -0.5);
//
// glColor3f(0,0,0);
// glVertex2f(0.5f, 0.5f);
//
// glColor3f(1.0f, 0, 0);
// glVertex2f(0.5f, -0.5f);
//
// glEnd();
// glutSwapBuffers();
GLenum errorCode = glGetError();
// if (errorCode != GL_NO_ERROR)
// {
// printf("errorCode = %d\n", errorCode);
// assert(false);
// }
assert(errorCode == GL_NO_ERROR);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, g_texture);
glEnableVertexAttribArray(eVertex);
glEnableVertexAttribArray(eColor);
glEnableVertexAttribArray(eTexture);
glUseProgram(g_program);
//设置Uniform的值
GLint loc = glGetUniformLocation(g_program,"texture0");
assert(loc>=0);
glUniform1i(loc, 0);
GLint value = 0;
glGetUniformiv(g_program, loc, &value);
assert(!value);
assert(glGetError() == GL_NO_ERROR);
//初始化数据
VF3_CB3_TF2_Quad quad;
initQuadWithData(2.0f, -2.0f, 4.0f, 4.0f, quad);
size_t offset = 0;
offset = OFFSET_MEMBER(VF3_CB3_TF2, m_vertex);
glVertexAttribPointer(eVertex, 3, GL_FLOAT, GL_FALSE, sizeof(VF3_CB3_TF2), (GLvoid*)((char*)&quad+offset));
offset = OFFSET_MEMBER(VF3_CB3_TF2, m_color);
glVertexAttribPointer(eColor, 3, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(VF3_CB3_TF2), (GLvoid*)((char*)&quad+offset));
offset = OFFSET_MEMBER(VF3_CB3_TF2, m_texture);
glVertexAttribPointer(eTexture, 2, GL_FLOAT, GL_FALSE, sizeof(VF3_CB3_TF2), (GLvoid*)((char*)&quad+offset));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(eVertex);
glDisableVertexAttribArray(eColor);
glDisableVertexAttribArray(eTexture);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
double factor = (w*1.0)/h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, factor, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0, 5, 0,0,0, 0,1,0);
}
void idle()
{
}
void initShader()
{
const GLchar* vertexSource[] = {vertex_source};
const GLchar* fragSource[] = {frag_source};
g_program = glCreateProgram();
GLenum err = glGetError();
if (err)
{
printf("error code = %d\n",err);
}
g_vertex_shader = glCreateShader(GL_VERTEX_SHADER);
g_frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
assert(g_program || g_vertex_shader || g_frag_shader);
glShaderSource(g_vertex_shader,1, vertexSource, 0);
glShaderSource(g_frag_shader, 1, fragSource, 0);
glCompileShader(g_vertex_shader);
glCompileShader(g_frag_shader);
GLint status = 0;
glGetShaderiv(g_vertex_shader, GL_COMPILE_STATUS, &status);
//assert(status);
if (!status)
{
GLsizei length = 0, written=0;
glGetShaderiv(g_vertex_shader, GL_INFO_LOG_LENGTH, &length);
GLchar* src = (GLchar*)malloc(length+1);
memset(src, 0, (length+1));
glGetShaderInfoLog(g_vertex_shader, length, &written, src);
printf("%s", src);
free(src);
return;
}
glGetShaderiv(g_frag_shader, GL_COMPILE_STATUS, &status);
//assert(status);
if (!status)
{
GLsizei length = 0, written=0;
glGetShaderiv(g_vertex_shader, GL_INFO_LOG_LENGTH, &length);
GLchar* src = (GLchar*)malloc(length+1);
memset(src, 0, (length+1));
glGetShaderInfoLog(g_vertex_shader, length, &written, src);
printf("%s", src);
free(src);
return;
}
glAttachShader(g_program, g_vertex_shader);
glAttachShader(g_program, g_frag_shader);
glBindAttribLocation(g_program,eVertex,attrib_vertex_name);
glBindAttribLocation(g_program,eColor, attrib_color_name);
glBindAttribLocation(g_program,eTexture,attrib_texture_name);
glLinkProgram(g_program);
glGetProgramiv(g_program, GL_LINK_STATUS,&status);
if(!status)
{
GLsizei bufSize = 0;
glGetProgramiv(g_program,GL_INFO_LOG_LENGTH, &bufSize);
GLchar* infoLog =(GLchar*) malloc(bufSize);
glGetProgramInfoLog(g_program,bufSize, 0, infoLog);
printf("link error:\n%s",infoLog);
return;
}
assert(glGetError() == GL_NO_ERROR);
//必须在调用glUseProgram之后再调用glUniformXXX接口
//否则会包GL_INVALID_OPERATION错误
// glUseProgram(g_program);
// GLint loc = glGetUniformLocation(g_program,"texture0");
// assert(loc>=0);
// glUniform1i(loc, 0);
//
// GLint value = 0;
// glGetUniformiv(g_program, loc, &value);
// assert(!value);
//
// GLenum errorCode = glGetError();
// assert(glGetError() == GL_NO_ERROR);
// printf("program compile and link success~\n");
}
void timer(int value)
{
if (value != g_timer_id)
return;
glutPostRedisplay();
glutTimerFunc(g_time_per_frame, timer, g_timer_id);
}
int _tmain(int argc, _TCHAR* argv[])
{
glutInit(&argc, argv);
//在窗口创建之前,必须要首先初始化显示模式
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
glutCreateWindow("GLSL");
glutInitWindowPosition(400, 200);
glutInitWindowSize(600, 600);
if(glewInit() != GLEW_NO_ERROR)
return -1;
init();
initShader();
glutDisplayFunc(render);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
//glutTimerFunc(g_time_per_frame,timer,g_timer_id);
glutMainLoop();
return 0;
}
下面这是没有加入颜色只应用坐标和纹理的效果将着色器的
"gl_FragColor = v_color * texture2D(texture0,v_texture) ;\n"
这行代码的v_color去掉或者改为v_color = vec4(1.0f, 1.0f, 1.0f, 1.0f)即可,其效果如下
呵呵,效果还不错吧,本人做OpenGL还是GLSL都是用的这个小mm测试!