?? vertexshaders.c
字號:
// VertexShaders.c
// OpenGL SuperBible, Chapter 22
// Demonstrates vertex shaders
// Program by Benjamin Lipchak
#include "../../Common/OpenGLSB.h" // System and OpenGL Stuff
#include "../../Common/GLTools.h" // System and OpenGL Stuff
#include <stdio.h>
#ifndef __APPLE__
PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
PFNGLBINDPROGRAMARBPROC glBindProgramARB;
PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
#endif
PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
PFNGLGETHANDLEARBPROC glGetHandleARB;
PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
PFNGLUNIFORM1FARBPROC glUniform1fARB;
PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
#ifndef __APPLE__
PFNGLACTIVETEXTUREPROC glActiveTexture;
#endif
GLboolean lowLevelAvailable = GL_FALSE;
GLboolean highLevelAvailable = GL_FALSE;
GLboolean useHighLevel = GL_FALSE;
#define SIMPLE 0
#define DIFFUSE 1
#define SPECULAR 2
#define SEPSPEC 3
#define TEXSPEC 4
#define THREELIGHTS 5
#define FOGCOORD 6
#define FOG 7
#define PTSIZE 8
#define STRETCH 9
#define TOTAL_SHADERS 10
GLuint ids[TOTAL_SHADERS]; // low-level shader object names
GLhandleARB vShader[TOTAL_SHADERS], progObj[TOTAL_SHADERS]; // high-level shader object handles
GLboolean needsValidation[TOTAL_SHADERS];
char *shaderNames[TOTAL_SHADERS] = {"simple", "diffuse", "specular", "sepspec", "texspec",
"3lights", "fogcoord", "fog", "ptsize", "stretch"};
GLint whichShader = SIMPLE; // current shader
#define LIGHT0_POS_SLOT 0 // locations for low-level program local parameters
#define LIGHT1_POS_SLOT 1
#define LIGHT2_POS_SLOT 2
#define SQUASH_STRETCH_SLOT 1
#define DENSITY_SLOT 1
GLint windowWidth = 512; // window size
GLint windowHeight = 512;
GLint mainMenu, shaderMenu; // menu handles
GLint maxTexSize; // maximum allowed size for 1D/2D texture
GLfloat cameraPos[] = { 100.0f, 75.0f, 150.0f, 1.0f};
GLfloat lightPos0[] = { 140.0f, 250.0f, 140.0f, 1.0f};
GLfloat lightPos1[] = { -140.0f, 250.0f, 140.0f, 1.0f};
GLfloat lightPos2[] = { 0.0f, 250.0f, -200.0f, 1.0f};
GLfloat squashStretch[] = {1.0f, 1.5f, 0.75f, 1.0f};
GLfloat fogColor[] = {0.5f, 0.8f, 0.5f, 1.0f};
GLfloat lightRotation = 0.0f;
GLfloat density = 0.005f;
#define MAX_INFO_LOG_SIZE 2048
// Create 1D texture to map NdotH to NdotH^128
GLvoid CreatePowMap(GLfloat r, GLfloat g, GLfloat b)
{
GLfloat texels[512 * 4];
GLint texSize = (maxTexSize > 512) ? 512 : maxTexSize;
GLint x;
for (x = 0; x < texSize; x++)
{
// Incoming N.H has been scaled by 8 and biased by -7 to take better
// advantage of the texture space. Otherwise, the texture will be
// entirely zeros until ~7/8 of the way into it. This way, we expand
// the useful 1/8 of the range and get better precision.
texels[x*4+0] = r * pow(((double)x / (double)(texSize-1)) * 0.125f + 0.875f, 128.0);
texels[x*4+1] = g * pow(((double)x / (double)(texSize-1)) * 0.125f + 0.875f, 128.0);
texels[x*4+2] = b * pow(((double)x / (double)(texSize-1)) * 0.125f + 0.875f, 128.0);
texels[x*4+3] = 1.0f;
}
// Make sure the first texel is exactly zero. Most
// incoming texcoords will clamp to this texel.
texels[0] = texels[1] = texels[2] = 0.0f;
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16, texSize, 0, GL_RGBA, GL_FLOAT, texels);
}
// Load shader from disk into a null-terminated string
GLubyte *LoadShaderText(const char *fileName)
{
GLubyte *shaderText = NULL;
GLint shaderLength = 0;
FILE *fp;
fp = fopen(fileName, "r");
if (fp != NULL)
{
while (fgetc(fp) != EOF)
{
shaderLength++;
}
rewind(fp);
shaderText = (GLubyte *)malloc(shaderLength+1);
if (shaderText != NULL)
{
fread(shaderText, 1, shaderLength, fp);
}
shaderText[shaderLength] = '\0';
fclose(fp);
}
return shaderText;
}
// Compile shaders
void PrepareShader(GLint shaderNum)
{
char fullFileName[255];
GLubyte *vsString;
// Create low-level shader objects and specify shader text
if (lowLevelAvailable)
{
GLint errorPos;
#ifdef __APPLE__
sprintf(fullFileName, "%s.vp", shaderNames[shaderNum]);
#else
sprintf(fullFileName, ".\\shaders\\%s.vp", shaderNames[shaderNum]);
#endif
vsString = LoadShaderText(fullFileName);
if (!vsString)
{
fprintf(stderr, "Unable to load \"%s\"\n", fullFileName);
Sleep(5000);
exit(0);
}
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ids[shaderNum]);
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(vsString), vsString);
free(vsString);
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
if (errorPos != -1)
{
fprintf(stderr, "Error in low-level vertex shader #%d at position %d!\n", shaderNum, errorPos);
fprintf(stderr, "Error string: %s\n", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
Sleep(5000);
exit(0);
}
}
// Create high-level shader objects and specify shader text
if (highLevelAvailable)
{
GLcharARB *vsStringPtr[1];
GLint success;
sprintf(fullFileName, ".\\shaders\\%s.vs", shaderNames[shaderNum]);
vsString = LoadShaderText(fullFileName);
if (!vsString)
{
fprintf(stderr, "Unable to load \"%s\"\n", fullFileName);
Sleep(5000);
exit(0);
}
vShader[shaderNum] = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
vsStringPtr[0] = vsString;
glShaderSourceARB(vShader[shaderNum], 1, vsStringPtr, NULL);
free(vsString);
// Compile shaders and check for any errors
glCompileShaderARB(vShader[shaderNum]);
glGetObjectParameterivARB(vShader[shaderNum], GL_OBJECT_COMPILE_STATUS_ARB, &success);
if (!success)
{
GLbyte infoLog[MAX_INFO_LOG_SIZE];
glGetInfoLogARB(vShader[shaderNum], MAX_INFO_LOG_SIZE, NULL, infoLog);
fprintf(stderr, "Error in high-level vertex shader #%d compilation!\n", shaderNum);
fprintf(stderr, "Info log: %s\n", infoLog);
Sleep(10000);
exit(0);
}
// Create program object, attach shader, then link
progObj[shaderNum] = glCreateProgramObjectARB();
glAttachObjectARB(progObj[shaderNum], vShader[shaderNum]);
glLinkProgramARB(progObj[shaderNum]);
glGetObjectParameterivARB(progObj[shaderNum], GL_OBJECT_LINK_STATUS_ARB, &success);
if (!success)
{
GLbyte infoLog[MAX_INFO_LOG_SIZE];
glGetInfoLogARB(progObj[shaderNum], MAX_INFO_LOG_SIZE, NULL, infoLog);
fprintf(stderr, "Error in high-level program #%d linkage!\n", shaderNum);
fprintf(stderr, "Info log: %s\n", infoLog);
Sleep(10000);
exit(0);
}
// Program object has changed, so we should revalidate
needsValidation[shaderNum] = GL_TRUE;
}
}
// Called to draw scene objects
void DrawModels(void)
{
GLTVector3 lightPosEye0, lightPosEye1, lightPosEye2;
GLTMatrix mv;
// Transform light position to eye space
glPushMatrix();
glRotatef(lightRotation, 0.0, 1.0, 0.0);
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
gltTransformPoint(lightPos0, mv, lightPosEye0);
if (whichShader == THREELIGHTS)
{
gltTransformPoint(lightPos1, mv, lightPosEye1);
gltTransformPoint(lightPos2, mv, lightPosEye2);
}
glPopMatrix();
if (useHighLevel)
{
GLint uniformLoc = glGetUniformLocationARB(progObj[whichShader], "lightPos0");
if (uniformLoc != -1)
{
glUniform3fvARB(uniformLoc, 1, lightPosEye0);
}
uniformLoc = glGetUniformLocationARB(progObj[whichShader], "lightPos1");
if (uniformLoc != -1)
{
glUniform3fvARB(uniformLoc, 1, lightPosEye1);
}
uniformLoc = glGetUniformLocationARB(progObj[whichShader], "lightPos2");
if (uniformLoc != -1)
{
glUniform3fvARB(uniformLoc, 1, lightPosEye2);
}
uniformLoc = glGetUniformLocationARB(progObj[whichShader], "squashStretch");
if (uniformLoc != -1)
{
glUniform3fvARB(uniformLoc, 1, squashStretch);
}
uniformLoc = glGetUniformLocationARB(progObj[whichShader], "density");
if (uniformLoc != -1)
{
glUniform1fARB(uniformLoc, density);
}
}
else
{
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LIGHT0_POS_SLOT, lightPosEye0);
if (whichShader == THREELIGHTS)
{
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LIGHT1_POS_SLOT, lightPosEye1);
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LIGHT2_POS_SLOT, lightPosEye2);
} else if (whichShader == STRETCH)
{
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, SQUASH_STRETCH_SLOT, squashStretch);
} else if (whichShader == FOG)
{
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, DENSITY_SLOT, density, 0.0f, 0.0f, 0.0f);
}
}
// Draw plane that the objects rest on
glColor3f(0.0f, 0.0f, 0.90f); // Blue
glNormal3f(0.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, -25.0f, -100.0f);
glVertex3f(-100.0f, -25.0f, 100.0f);
glVertex3f(100.0f, -25.0f, 100.0f);
glVertex3f(100.0f, -25.0f, -100.0f);
glEnd();
// Draw red cube
glColor3f(1.0f, 0.0f, 0.0f);
glutSolidCube(48.0f);
// Draw green sphere
glColor3f(0.0f, 1.0f, 0.0f);
glPushMatrix();
glTranslatef(-60.0f, 0.0f, 0.0f);
glutSolidSphere(25.0f, 50, 50);
glPopMatrix();
// Draw magenta torus
glColor3f(1.0f, 0.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0f, 0.0f, 60.0f);
glutSolidTorus(8.0f, 16.0f, 50, 50);
glPopMatrix();
if (whichShader == STRETCH)
{
// Cone and teapot are rotated such that their
// Y and Z squash scales must be switched
GLfloat rotatedSquashStretch[4];
rotatedSquashStretch[0] = squashStretch[0];
rotatedSquashStretch[1] = squashStretch[2];
rotatedSquashStretch[2] = squashStretch[1];
rotatedSquashStretch[3] = squashStretch[3];
if (useHighLevel)
{
GLint uniformLoc = glGetUniformLocationARB(progObj[whichShader], "squashStretch");
if (uniformLoc != -1)
{
glUniform3fvARB(uniformLoc, 1, rotatedSquashStretch);
}
}
else
{
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, SQUASH_STRETCH_SLOT, rotatedSquashStretch);
}
}
// Draw yellow cone
glColor3f(1.0f, 1.0f, 0.0f);
glPushMatrix();
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
glTranslatef(60.0f, 0.0f, -24.0f);
glutSolidCone(25.0f, 50.0f, 50, 50);
glPopMatrix();
// Draw cyan teapot
glColor3f(0.0f, 1.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0f, 0.0f, -60.0f);
glutSolidTeapot(25.0f);
glPopMatrix();
}
// Called to draw scene
void RenderScene(void)
{
// Track camera angle
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 1.0f, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cameraPos[0], cameraPos[1], cameraPos[2],
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glViewport(0, 0, windowWidth, windowHeight);
if ((whichShader == FOGCOORD) || (whichShader == FOG))
{
// Use a green-gray color for fog
glClearColor(fogColor[0], fogColor[1], fogColor[2], fogColor[3]);
glFogf(GL_FOG_DENSITY, density);
}
else
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
}
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Validate our shader before first use
if (needsValidation[whichShader])
{
GLint success;
glValidateProgramARB(progObj[whichShader]);
glGetObjectParameterivARB(progObj[whichShader], GL_OBJECT_VALIDATE_STATUS_ARB, &success);
if (!success)
{
GLbyte infoLog[MAX_INFO_LOG_SIZE];
glGetInfoLogARB(progObj[whichShader], MAX_INFO_LOG_SIZE, NULL, infoLog);
fprintf(stderr, "Error in program #%d validation!\n", whichShader);
fprintf(stderr, "Info log: %s\n", infoLog);
Sleep(10000);
exit(0);
}
needsValidation[whichShader] = GL_FALSE;
}
// Draw objects in the scene
DrawModels();
if (glGetError() != GL_NO_ERROR)
fprintf(stderr, "GL Error!\n");
// Flush drawing commands
glutSwapBuffers();
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
const GLubyte *version;
GLint i;
fprintf(stdout, "Vertex Shaders Demo\n\n");
// Make sure required functionality is available!
if (gltIsExtSupported("GL_ARB_vertex_shader") &&
gltIsExtSupported("GL_ARB_shader_objects") &&
gltIsExtSupported("GL_ARB_shading_language_100"))
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -