?? vertexblending.c
字號:
// VertexBlending.c
// OpenGL SuperBible, Chapter 22
// Demonstrates vertex blending
// 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;
PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
#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;
PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix3fvARB;
PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
GLboolean lowLevelAvailable = GL_FALSE;
GLboolean highLevelAvailable = GL_FALSE;
GLboolean useHighLevel = GL_FALSE;
GLboolean useBlending = GL_TRUE;
GLboolean showBones = GL_FALSE;
#define TOTAL_SHADERS 1
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] = {"skinning"};
#define WEIGHT_SLOT 1 // locations for low-level attrib and program local parameters
#define LIGHT_POS_SLOT 0
#define MODELVIEW2_SLOT 1
GLint lightPosLoc, mv2Loc, mv2ITLoc; // locations for high-level uniforms
GLint weightLoc; // locations for high-level attribs
GLint windowWidth = 512; // window size
GLint windowHeight = 512;
GLint mainMenu; // menu handles
GLint maxTexSize; // maximum allowed size for 1D/2D texture
GLfloat cameraPos[] = { 50.0f, 75.0f, 50.0f, 1.0f};
GLfloat lightPos[] = { -50.0f, 100.0f, 50.0f, 1.0f};
GLfloat elbowBend = 45.0f;
GLfloat sphereOfInfluence = 1.0f; // how much of each limb gets blended
#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);
}
lightPosLoc = glGetUniformLocationARB(progObj[0], "lightPos");
mv2Loc = glGetUniformLocationARB(progObj[0], "mv2");
mv2ITLoc = glGetUniformLocationARB(progObj[0], "mv2IT");
weightLoc = glGetAttribLocationARB(progObj[0], "weight");
// Program object has changed, so we should revalidate
needsValidation[shaderNum] = GL_TRUE;
}
}
// Draw a cylinder with supplied dimensions
void DrawCylinder(GLfloat length, GLfloat diameter1, GLfloat diameter2,
GLfloat startWeight, GLfloat endWeight)
{
int numFacets = 50;
int numSections = 50;
GLfloat angleIncr = (2.0f * 3.14159f) / (float)numFacets;
GLfloat sectionLength = length / numSections;
GLfloat wEnd, influenceStart;
int i, j;
// Determine where our influence starts for this limb
if (startWeight == 0.5f)
{
influenceStart = sphereOfInfluence;
}
else
{
influenceStart = 1.0f - sphereOfInfluence;
}
// Skin
for (i = 0; i < numFacets; i++)
{
// Calculate geometry for this facet
GLfloat angle1 = i * angleIncr;
GLfloat angle2 = ((i+1)%numFacets) * angleIncr;
GLfloat y1AtFirstEnd = sin(angle1) * diameter1;
GLfloat y1AtOtherEnd = sin(angle1) * diameter2;
GLfloat z1AtFirstEnd = cos(angle1) * diameter1;
GLfloat z1AtOtherEnd = cos(angle1) * diameter2;
GLfloat y2AtFirstEnd = sin(angle2) * diameter1;
GLfloat y2AtOtherEnd = sin(angle2) * diameter2;
GLfloat z2AtFirstEnd = cos(angle2) * diameter1;
GLfloat z2AtOtherEnd = cos(angle2) * diameter2;
GLfloat n1y = y1AtFirstEnd;
GLfloat n1z = z1AtFirstEnd;
GLfloat n2y = y2AtFirstEnd;
GLfloat n2z = z2AtFirstEnd;
// One strip per facet
glBegin(GL_QUAD_STRIP);
glVertexAttrib1fARB(useHighLevel ? weightLoc : WEIGHT_SLOT,
useBlending ? startWeight : 1.0f);
glNormal3f(0.0f, n1y, n1z);
glVertex3f(0.0f, y1AtFirstEnd, z1AtFirstEnd);
glNormal3f(0.0f, n2y, n2z);
glVertex3f(0.0f, y2AtFirstEnd, z2AtFirstEnd);
for (j = 0; j < numSections; j++)
{
// Calculate geometry for end of this quad
GLfloat paramEnd = (float)(j+1) / (float)numSections;
GLfloat lengthEnd = paramEnd * length;
GLfloat y1End = y1AtFirstEnd + (paramEnd * (y1AtOtherEnd - y1AtFirstEnd));
GLfloat z1End = z1AtFirstEnd + (paramEnd * (z1AtOtherEnd - z1AtFirstEnd));
GLfloat y2End = y2AtFirstEnd + (paramEnd * (y2AtOtherEnd - y2AtFirstEnd));
GLfloat z2End = z2AtFirstEnd + (paramEnd * (z2AtOtherEnd - z2AtFirstEnd));
// Calculate vertex weights
if (!useBlending)
{
wEnd = 1.0f;
}
else if (paramEnd <= influenceStart)
{
// Map params [0,influenceStart] to weights [0,1]
GLfloat p = (paramEnd * (1.0f/influenceStart));
// We're in the first half of the cylinder: startWeight -> 1
wEnd = startWeight + p * (1.0f - startWeight);
}
else
{
// Map params [influenceStart,1] to weights [0,1]
GLfloat p = (paramEnd-influenceStart) * (1.0f/(1.0f-influenceStart));
// We're in the second half of the cylinder: 1 -> endWeight
wEnd = 1.0f + p * (endWeight - 1.0f);
}
glVertexAttrib1fARB(useHighLevel ? weightLoc : WEIGHT_SLOT, wEnd);
glNormal3f(0.0f, n1y, n1z);
glVertex3f(lengthEnd, y1End, z1End);
glNormal3f(0.0f, n2y, n2z);
glVertex3f(lengthEnd, y2End, z2End);
}
// End facet strip
glEnd();
}
if (showBones)
{
// Skeleton
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glColor4f(1.0f, 1.0f, 1.0f, 0.75f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertexAttrib1fARB(useHighLevel ? weightLoc : WEIGHT_SLOT, 1.0f);
glBegin(GL_LINES);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(length, 0.0f, 0.0f);
glEnd();
glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_POINTS);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(length, 0.0f, 0.0f);
glEnd();
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
}
}
// Called to draw scene objects
void DrawModels(void)
{
GLTVector3 lightPosEye;
GLTMatrix mv, mv2;
// Transform light position to eye space
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
gltTransformPoint(lightPos, mv, lightPosEye);
if (useHighLevel)
{
glUniform3fvARB(lightPosLoc, 1, lightPosEye);
}
else
{
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LIGHT_POS_SLOT, lightPosEye);
}
// Setup modelview matrices for upper arm
glPushMatrix();
glRotatef(elbowBend, 0.0f, 0.0f, 1.0f);
glTranslatef(-50.0f, 0.0f, 0.0f);
glGetFloatv(GL_MODELVIEW_MATRIX, mv2);
glPopMatrix();
glTranslatef(-50.0f, 0.0f, 0.0f);
if (useHighLevel)
{
GLTMatrix mv2IT_4x4;
GLfloat mv2IT_3x3[9];
GLint i;
glUniformMatrix4fvARB(mv2Loc, 1, GL_FALSE, mv2);
gltInvertMatrix(mv2, mv2IT_4x4);
// Take upper left 3x3 for 2nd normal matrix
for (i = 0; i < 9; i++)
{
mv2IT_3x3[i] = mv2IT_4x4[((i/3)*4)+(i%3)];
}
glUniformMatrix3fvARB(mv2ITLoc, 1, GL_TRUE, mv2IT_3x3);
}
else
{
glMatrixMode(GL_MATRIX0_ARB);
glLoadMatrixf(mv2);
glMatrixMode(GL_MODELVIEW);
}
// Draw upper arm cylinder
glColor3f(0.0f, 0.0f, 0.90f); // Blue
// 50 long, 10 shoulder, 9 elbow, with weights applied to second half
DrawCylinder(50.0f, 15.0f, 9.0f, 1.0f, 0.5f);
// Setup modelview matrices for forearm
glTranslatef(50.0f, 0.0f, 0.0f);
glPushMatrix();
glGetFloatv(GL_MODELVIEW_MATRIX, mv2);
glPopMatrix();
glRotatef(elbowBend, 0.0f, 0.0f, 1.0f);
if (useHighLevel)
{
GLTMatrix mv2IT_4x4;
GLfloat mv2IT_3x3[9];
GLint i;
glUniformMatrix4fvARB(mv2Loc, 1, GL_FALSE, mv2);
gltInvertMatrix(mv2, mv2IT_4x4);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -