我有一个程序,该程序使一组球面具有一组位置。我想把我的程序放在一个课堂上。我将所有函数都放在一个类中,并将主函数的内容放入“ helper”函数中。我通过实例化我的类,然后在main函数(类之外)中调用它来调用helper。我只得到白屏。
除了必须将Sphere对象放入构造函数中,并且将显示/重塑回调函数通过另一个静态函数传递给glutDisplay / ReshapeFunc之外,我保持了所有相同的方法(因为我从非静态上下文错误中无法访问它们) )
使用建议的答案更新代码:
class Test {
public:
Sphere sphere2;
static Test *pThis;
Test (int i) {
// radius, sectors, stacks, smooth(default)
pThis = this;
sphere2.set(.05,36,18);
}
// constants
const int SCREEN_WIDTH = 790;
const int SCREEN_HEIGHT = 790;
const float CAMERA_DISTANCE = 4.0f;
const int TEXT_WIDTH = 8;
const int TEXT_HEIGHT = 13;
// blinn shading with texture =============================
const char* vsSource = R"(
// GLSL version
#version 110
// uniforms
uniform mat4 matrixModelView;
uniform mat4 matrixNormal;
uniform mat4 matrixModelViewProjection;
//uniform for offsets
//uniform vec2 offsets[100]; //----------------
// vertex attribs (input)
attribute vec3 vertexPosition;
attribute vec3 vertexNormal;
attribute vec2 vertexTexCoord;
attribute vec3 aOffset;
// varyings (output)
varying vec3 esVertex, esNormal;
varying vec2 texCoord0;
void main()
{
esVertex = vec3(matrixModelView * vec4(vertexPosition, 1.0));
esNormal = vec3(matrixNormal * vec4(vertexNormal, 1.0));
texCoord0 = vertexTexCoord;
//getting offset for each id
//vec2 offset = offsets[gl_InstanceID]; //-----------------
gl_Position = matrixModelViewProjection * vec4(vertexPosition + aOffset, 1.0);
}
)";
const char* fsSource = R"(
// GLSL version
#version 110
// uniforms
uniform vec4 lightPosition; // should be in the eye space
uniform vec4 lightAmbient; // light ambient color
uniform vec4 lightDiffuse; // light diffuse color
uniform vec4 lightSpecular; // light specular color
uniform vec4 materialAmbient; // material ambient color
uniform vec4 materialDiffuse; // material diffuse color
uniform vec4 materialSpecular; // material specular color
uniform float materialShininess; // material specular shininess
uniform sampler2D map0; // texture map #1
uniform bool textureUsed; // flag for texture
// varyings
varying vec3 esVertex, esNormal;
varying vec2 texCoord0;
void main()
{
vec3 normal = normalize(esNormal);
vec3 light;
if(lightPosition.w == 0.0)
{
light = normalize(lightPosition.xyz);
}
else
{
light = normalize(lightPosition.xyz - esVertex);
}
vec3 view = normalize(-esVertex);
vec3 halfv = normalize(light + view);
vec3 color = lightAmbient.rgb * materialAmbient.rgb; // begin with ambient
float dotNL = max(dot(normal, light), 0.0);
color += lightDiffuse.rgb * materialDiffuse.rgb * dotNL; // add diffuse
if(textureUsed)
color *= texture2D(map0, texCoord0).rgb; // modulate texture map
float dotNH = max(dot(normal, halfv), 0.0);
color += pow(dotNH, materialShininess) * lightSpecular.rgb * materialSpecular.rgb; // add specular
// set frag color
gl_FragColor = vec4(color, materialDiffuse.a);
}
)";
// global variables
void *font = GLUT_BITMAP_8_BY_13;
int screenWidth;
int screenHeight;
float cameraAngleX;
float cameraAngleY;
float cameraDistance;
int drawMode;
bool vboSupported;
GLuint vboId1 = 0, vboId2 = 0; // IDs of VBO for vertex arrays
GLuint iboId1 = 0, iboId2 = 0; // IDs of VBO for index array
GLuint texId;
int imageWidth;
int imageHeight;
Matrix4 matrixModelView;
Matrix4 matrixProjection;
// GLSL
GLuint progId = 0; // ID of GLSL program
bool glslSupported;
GLint uniformMatrixModelView;
GLint uniformMatrixModelViewProjection;
GLint uniformMatrixNormal;
GLint uniformLightPosition;
GLint uniformLightAmbient;
GLint uniformLightDiffuse;
GLint uniformLightSpecular;
GLint uniformMaterialAmbient;
GLint uniformMaterialDiffuse;
GLint uniformMaterialSpecular;
GLint uniformMaterialShininess;
GLint uniformMap0;
GLint uniformTextureUsed;
GLint attribVertexPosition;
GLint attribVertexNormal;
GLint attribVertexTexCoord;
int instances; //# instances of instancing to draw
float radius = .05f; //sphere radius
std::vector<glm::vec3> positions;
// sphere: min sector = 3, min stack = 2
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// initialize GLUT for windowing
///////////////////////////////////////////////////////////////////////////////
int initGLUT(int argc, char **argv)
{
// GLUT stuff for windowing
// initialization openGL window.
// it is called before any other GLUT routine
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); // display mode
glutInitWindowSize(screenWidth, screenHeight); // window size
glutInitWindowPosition(100, 100); // window location
// finally, create a window with openGL context
// Window will not displayed until glutMainLoop() is called
// it returns a unique ID
int handle = glutCreateWindow(argv[0]); // param is the title of window
// register GLUT callback functions
glutDisplayFunc(displayHelper);
//glutTimerFunc(33, timerCB, 33); // redraw only every given millisec
glutReshapeFunc(reshapeHelper);
//glutKeyboardFunc(keyboardCB);
//glutMouseFunc(mouseCB);
//glutMotionFunc(mouseMotionCB);
return handle;
}
///////////////////////////////////////////////////////////////////////////////
// initialize OpenGL
// disable unused features
///////////////////////////////////////////////////////////////////////////////
void initGL()
{
glShadeModel(GL_SMOOTH); // shading mathod: GL_SMOOTH or GL_FLAT
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
// enable /disable features
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
//glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glEnable(GL_CULL_FACE);
// track material ambient and diffuse from surface color, call it before glEnable(GL_COLOR_MATERIAL)
//glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
//glEnable(GL_COLOR_MATERIAL);
glClearColor(0, 0, 0, 0); // background color
glClearStencil(0); // clear stencil buffer
glClearDepth(1.0f); // 0 is near, 1 is far
glDepthFunc(GL_LEQUAL);
initLights();
}
///////////////////////////////////////////////////////////////////////////////
// create glsl programs
///////////////////////////////////////////////////////////////////////////////
bool initGLSL()
{
const int MAX_LENGTH = 2048;
char log[MAX_LENGTH];
int logLength = 0;
// create shader and program
GLuint vsId = glCreateShader(GL_VERTEX_SHADER);
GLuint fsId = glCreateShader(GL_FRAGMENT_SHADER);
progId = glCreateProgram();
// load shader sources
glShaderSource(vsId, 1, &vsSource, NULL);
glShaderSource(fsId, 1, &fsSource, NULL);
// compile shader sources
glCompileShader(vsId);
glCompileShader(fsId);
glUseProgram(progId);
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//given array of positions
//glm::vec3 positions[5] ={glm::vec3(0,0,0),glm::vec3(.2,.2,-.2),glm::vec3(.4,.6,0),glm::vec3(.6,.6,0),glm::vec3(.8,.8,.3)};
positions.push_back(glm::vec3(0,0,0));
positions.push_back(glm::vec3(.2,.2,-.2));
positions.push_back(glm::vec3(.4,.6,0));
positions.push_back(glm::vec3(.6,.6,0));
positions.push_back(glm::vec3(.8,.8,.3));
int positionSize = positions.size();
//number of points in between positions
float pointsInBetween = 100;
//generate array containing interpolated points
glm::vec3 interpolated[positionSize + positionSize * ((int)pointsInBetween)]; //array of interpolated points
int interSize = sizeof(interpolated)/sizeof(interpolated[0]);
int index = 0; //keep track of where to add next element
//iterating over every position
for (int i = 1; i < positionSize; i++) {
//add points in between
for (int j = -1; j < pointsInBetween; j++) {
float alpha = 1.0/(pointsInBetween + 1.0) + j*1.0/(pointsInBetween + 1.0);
//get starting & ending positions
float x = positions[i][0]; float x_prev = positions[i - 1][0];
float y = positions[i][1]; float y_prev = positions[i - 1][1];
float z = positions[i][2]; float z_prev = positions[i - 1][2];
//calculate position of new intermediate vector
float a = alpha * x + (1.0 - alpha) * x_prev;
float b = alpha * y + (1.0 - alpha) * y_prev;
float c = alpha * z + (1.0 - alpha) * z_prev;
//add to array
interpolated[index++] = glm::vec3(a, b,c);
}
}
interpolated[index++] = positions[positionSize - 1]; //have to add final position
//generate translations array
instances = interSize;
glm::vec3 translations[interSize];
translations[0] = interpolated[0] - glm::vec3(0,0,0); //add initial point
//calculating and adding each translation to translation array
for (int i = 1; i < interSize; i++) {
translations[i] = interpolated[i] - interpolated[i-1] + translations[i-1];
}
unsigned int instanceVBO;
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * sizeof(translations)/sizeof(translations[0]), &translations[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribDivisorARB(3, 1);
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//@@ debug
int vsStatus, fsStatus;
glGetShaderiv(vsId, GL_COMPILE_STATUS, &vsStatus);
if(vsStatus == GL_FALSE)
{
glGetShaderiv(vsId, GL_INFO_LOG_LENGTH, &logLength);
glGetShaderInfoLog(vsId, MAX_LENGTH, &logLength, log);
std::cout << "===== Vertex Shader Log =====\n" << log << std::endl;
}
glGetShaderiv(fsId, GL_COMPILE_STATUS, &fsStatus);
if(fsStatus == GL_FALSE)
{
glGetShaderiv(fsId, GL_INFO_LOG_LENGTH, &logLength);
glGetShaderInfoLog(fsId, MAX_LENGTH, &logLength, log);
std::cout << "===== Fragment Shader Log =====\n" << log << std::endl;
}
// attach shaders to the program
glAttachShader(progId, vsId);
glAttachShader(progId, fsId);
// link program
glLinkProgram(progId);
// get uniform/attrib locations
glUseProgram(progId);
uniformMatrixModelView = glGetUniformLocation(progId, "matrixModelView");
uniformMatrixModelViewProjection = glGetUniformLocation(progId, "matrixModelViewProjection");
uniformMatrixNormal = glGetUniformLocation(progId, "matrixNormal");
uniformLightPosition = glGetUniformLocation(progId, "lightPosition");
uniformLightAmbient = glGetUniformLocation(progId, "lightAmbient");
uniformLightDiffuse = glGetUniformLocation(progId, "lightDiffuse");
uniformLightSpecular = glGetUniformLocation(progId, "lightSpecular");
uniformMaterialAmbient = glGetUniformLocation(progId, "materialAmbient");
uniformMaterialDiffuse = glGetUniformLocation(progId, "materialDiffuse");
uniformMaterialSpecular = glGetUniformLocation(progId, "materialSpecular");
uniformMaterialShininess = glGetUniformLocation(progId, "materialShininess");
uniformMap0 = glGetUniformLocation(progId, "map0");
uniformTextureUsed = glGetUniformLocation(progId, "textureUsed");
attribVertexPosition = glGetAttribLocation(progId, "vertexPosition");
attribVertexNormal = glGetAttribLocation(progId, "vertexNormal");
attribVertexTexCoord = glGetAttribLocation(progId, "vertexTexCoord");
// set uniform values
float lightPosition[] = {0, 0, 1, 0};
float lightAmbient[] = {0.3f, 0.3f, 0.3f, 1};
float lightDiffuse[] = {0.7f, 0.7f, 0.7f, 1};
float lightSpecular[] = {1.0f, 1.0f, 1.0f, 1};
float materialAmbient[] = {0.5f, 0.5f, 0.5f, 1};
float materialDiffuse[] = {0.7f, 0.7f, 0.7f, 1};
float materialSpecular[] = {0.4f, 0.4f, 0.4f, 1};
float materialShininess = 16;
glUniform4fv(uniformLightPosition, 1, lightPosition);
glUniform4fv(uniformLightAmbient, 1, lightAmbient);
glUniform4fv(uniformLightDiffuse, 1, lightDiffuse);
glUniform4fv(uniformLightSpecular, 1, lightSpecular);
glUniform4fv(uniformMaterialAmbient, 1, materialAmbient);
glUniform4fv(uniformMaterialDiffuse, 1, materialDiffuse);
glUniform4fv(uniformMaterialSpecular, 1, materialSpecular);
glUniform1f(uniformMaterialShininess, materialShininess);
glUniform1i(uniformMap0, 0);
glUniform1i(uniformTextureUsed, 1);
// unbind GLSL
glUseProgram(0);
// check GLSL status
int linkStatus;
glGetProgramiv(progId, GL_LINK_STATUS, &linkStatus);
if(linkStatus == GL_FALSE)
{
glGetProgramiv(progId, GL_INFO_LOG_LENGTH, &logLength);
glGetProgramInfoLog(progId, MAX_LENGTH, &logLength, log);
std::cout << "===== GLSL Program Log =====\n" << log << std::endl;
return false;
}
else
{
return true;
}
}
///////////////////////////////////////////////////////////////////////////////
// initialize global variables
///////////////////////////////////////////////////////////////////////////////
bool initSharedMem()
{
screenWidth = SCREEN_WIDTH;
screenHeight = SCREEN_HEIGHT;
cameraAngleX = cameraAngleY = 0.0f;
cameraDistance = CAMERA_DISTANCE;
drawMode = 0; // 0:fill, 1: wireframe, 2:points
// debug
sphere2.printSelf();
return true;
}
///////////////////////////////////////////////////////////////////////////////
// clean up global vars
///////////////////////////////////////////////////////////////////////////////
void clearSharedMem()
{
// clean up VBOs
if(vboSupported)
{
glDeleteBuffers(1, &vboId1);
glDeleteBuffers(1, &iboId1);
glDeleteBuffers(1, &vboId2);
glDeleteBuffers(1, &iboId2);
vboId1 = iboId1 = 0;
vboId2 = iboId2 = 0;
}
}
///////////////////////////////////////////////////////////////////////////////
// initialize lights
///////////////////////////////////////////////////////////////////////////////
void initLights()
{
// set up light colors (ambient, diffuse, specular)
GLfloat lightKa[] = {.3f, .3f, .3f, 1.0f}; // ambient light
GLfloat lightKd[] = {.7f, .7f, .7f, 1.0f}; // diffuse light
GLfloat lightKs[] = {1, 1, 1, 1}; // specular light
glLightfv(GL_LIGHT0, GL_AMBIENT, lightKa);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightKd);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightKs);
// position the light
float lightPos[4] = {0, 0, 1, 0}; // directional light
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_LIGHT0); // MUST enable each light source after configuration
}
///////////////////////////////////////////////////////////////////////////////
// set camera position and lookat direction
///////////////////////////////////////////////////////////////////////////////
void setCamera(float posX, float posY, float posZ, float targetX, float targetY, float targetZ)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(posX, posY, posZ, targetX, targetY, targetZ, 0, 1, 0); // eye(x,y,z), focal(x,y,z), up(x,y,z)
}
///////////////////////////////////////////////////////////////////////////////
// load raw image as a texture
///////////////////////////////////////////////////////////////////////////////
GLuint loadTexture(const char* fileName, bool wrap)
{
Image::Bmp bmp;
if(!bmp.read(fileName))
return 0; // exit if failed load image
// get bmp info
int width = bmp.getWidth();
int height = bmp.getHeight();
const unsigned char* data = bmp.getDataRGB();
GLenum type = GL_UNSIGNED_BYTE; // only allow BMP with 8-bit per channel
// We assume the image is 8-bit, 24-bit or 32-bit BMP
GLenum format;
int bpp = bmp.getBitCount();
if(bpp == 8)
format = GL_LUMINANCE;
else if(bpp == 24)
format = GL_RGB;
else if(bpp == 32)
format = GL_RGBA;
else
return 0; // NOT supported, exit
// gen texture ID
GLuint texture;
glGenTextures(1, &texture);
// set active texture and configure it
glBindTexture(GL_TEXTURE_2D, texture);
// select modulate to mix texture with color for shading
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
// if wrap is true, the texture wraps over at the edges (repeat)
// ... false, the texture ends at the edges (clamp)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap ? GL_REPEAT : GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap ? GL_REPEAT : GL_CLAMP);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// copy texture data
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data);
//glGenerateMipmap(GL_TEXTURE_2D);
// build our texture mipmaps
switch(bpp)
{
case 8:
gluBuild2DMipmaps(GL_TEXTURE_2D, 1, width, height, GL_LUMINANCE, type, data);
break;
case 24:
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, type, data);
break;
case 32:
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, type, data);
break;
}
return texture;
}
///////////////////////////////////////////////////////////////////////////////
// display info messages
///////////////////////////////////////////////////////////////////////////////
void showInfo()
{
// backup current model-view matrix
glPushMatrix(); // save current modelview matrix
glLoadIdentity(); // reset modelview matrix
// set to 2D orthogonal projection
glMatrixMode(GL_PROJECTION); // switch to projection matrix
glPushMatrix(); // save current projection matrix
glLoadIdentity(); // reset projection matrix
//gluOrtho2D(0, screenWidth, 0, screenHeight); // set to orthogonal projection
glOrtho(0, screenWidth, 0, screenHeight, -1, 1); // set to orthogonal projection
float color[4] = {1, 1, 1, 1};
std::stringstream ss;
ss << std::fixed << std::setprecision(3);
// unset floating format
ss << std::resetiosflags(std::ios_base::fixed | std::ios_base::floatfield);
// restore projection matrix
glPopMatrix(); // restore to previous projection matrix
// restore modelview matrix
glMatrixMode(GL_MODELVIEW); // switch to modelview matrix
glPopMatrix(); // restore to previous modelview matrix
}
///////////////////////////////////////////////////////////////////////////////
// set projection matrix as orthogonal
///////////////////////////////////////////////////////////////////////////////
void toOrtho()
{
const float N = -1.0f;
const float F = 1.0f;
// set viewport to be the entire window
glViewport(0, 0, (GLsizei)screenWidth, (GLsizei)screenHeight);
// construct ortho projection matrix
matrixProjection.identity();
matrixProjection[0] = 2 / screenWidth;
matrixProjection[5] = 2 / screenHeight;
matrixProjection[10] = -2 / (F - N);
matrixProjection[14] = -(F + N) / (F - N);
// set orthographic viewing frustum
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(matrixProjection.get());
//glLoadIdentity();
//glOrtho(0, screenWidth, 0, screenHeight, -1, 1);
// switch to modelview matrix in order to set scene
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
///////////////////////////////////////////////////////////////////////////////
// set the projection matrix as perspective
///////////////////////////////////////////////////////////////////////////////
void toPerspective()
{
const float N = 0.1f;
const float F = 100.0f;
const float DEG2RAD = 3.141592f / 180;
const float FOV_Y = 40.0f * DEG2RAD;
// set viewport to be the entire window
glViewport(0, 0, (GLsizei)screenWidth, (GLsizei)screenHeight);
// construct perspective projection matrix
float aspectRatio = (float)(screenWidth) / screenHeight;
float tangent = tanf(FOV_Y / 2.0f); // tangent of half fovY
float h = N * tangent; // half height of near plane
float w = h * aspectRatio; // half width of near plane
matrixProjection.identity();
matrixProjection[0] = N / w;
matrixProjection[5] = N / h;
matrixProjection[10] = -(F + N) / (F - N);
matrixProjection[11] = -1;
matrixProjection[14] = -(2 * F * N) / (F - N);
matrixProjection[15] = 0;
// set perspective viewing frustum
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(matrixProjection.get());
//@@ equivalent fixed pipeline
//glLoadIdentity();
//gluPerspective(40.0f, (float)(screenWidth)/screenHeight, 0.1f, 100.0f); // FOV, AspectRatio, NearClip, FarClip
// switch to modelview matrix in order to set scene
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//=============================================================================
// CALLBACKS
//=============================================================================
void displayCB()
{
if(!vboSupported || !glslSupported)
return;
// clear buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// transform camera (view)
Matrix4 matrixView;
matrixView.translate(0, 0, -cameraDistance);
// common model matrix
Matrix4 matrixModelCommon;
//matrixModelCommon.rotateX(-90); //-90 matrixModelCommon.rotateY(); //cameraAngleY matrixModelCommon.rotateX(); //cameraAngleX
// model matrix for each instance
Matrix4 matrixModel2(matrixModelCommon); // center
//matrixModel2.translate(0, 0, 0); // shift right
// bind GLSL, texture
glUseProgram(progId);
glBindTexture(GL_TEXTURE_2D, texId);
// activate attribs
glEnableVertexAttribArray(attribVertexPosition);
glEnableVertexAttribArray(attribVertexNormal);
glEnableVertexAttribArray(attribVertexTexCoord);
// left and center spheres do not use texture
glUniform1i(uniformTextureUsed, 0);
// bind vbo for smooth sphere (center and right)
glBindBuffer(GL_ARRAY_BUFFER, vboId2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboId2);
// set attrib arrays using glVertexAttribPointer()
int stride = sphere2.getInterleavedStride();
glVertexAttribPointer(attribVertexPosition, 3, GL_FLOAT, false, stride, 0);
glVertexAttribPointer(attribVertexNormal, 3, GL_FLOAT, false, stride, (void*)(3 * sizeof(float)));
glVertexAttribPointer(attribVertexTexCoord, 2, GL_FLOAT, false, stride, (void*)(6 * sizeof(float)));
// set matrix uniforms for center sphere
matrixModelView = matrixView * matrixModel2;
Matrix4 matrixModelViewProjection = matrixProjection * matrixModelView;
Matrix4 matrixNormal = matrixModelView;
matrixNormal.setColumn(3, Vector4(0,0,0,1));
glUniformMatrix4fv(uniformMatrixModelView, 1, false, matrixModelView.get());
glUniformMatrix4fv(uniformMatrixModelViewProjection, 1, false, matrixModelViewProjection.get());
glUniformMatrix4fv(uniformMatrixNormal, 1, false, matrixNormal.get());
// draw center sphere
glDrawElementsInstancedARB(GL_TRIANGLES, // primitive type
sphere2.getIndexCount(), // # of indices
GL_UNSIGNED_INT, // data type
(void*)0, instances); // ptr to indices
glDisableVertexAttribArray(attribVertexPosition);
glDisableVertexAttribArray(attribVertexNormal);
glDisableVertexAttribArray(attribVertexTexCoord);
// unbind
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glUseProgram(0);
showInfo(); // print max range of glDrawRangeElements
glutSwapBuffers();
}
void reshapeCB(int w, int h)
{
screenWidth = w;
screenHeight = h;
toPerspective();
std::cout << "window resized: " << w << " x " << h << std::endl;
#ifdef _WIN32
HWND handle = ::GetActiveWindow();
RECT rect;
::GetWindowRect(handle, &rect);
std::cout << "window size: " << (rect.right - rect.left) << "x" << (rect.bottom - rect.top) << std::endl;
#endif
}
//
int helper(int argc, char **argv)
{
// init global vars
initSharedMem();
// init GLUT and GL
initGLUT(argc, argv);
initGL();
// get OpenGL extensions
glExtension& ext = glExtension::getInstance();
vboSupported = ext.isSupported("GL_ARB_vertex_buffer_object");
if(vboSupported)
{
// create vertex buffer objects
glGenBuffers(1, &vboId2);
glBindBuffer(GL_ARRAY_BUFFER, vboId2);
glBufferData(GL_ARRAY_BUFFER, sphere2.getInterleavedVertexSize(), sphere2.getInterleavedVertices(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &iboId2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboId2);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphere2.getIndexSize(), sphere2.getIndices(), GL_STATIC_DRAW);
// unbind
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
std::cout << "Video card supports GL_ARB_vertex_buffer_object." << std::endl;
}
else
{
std::cout << "[WARNING] Video card does NOT support GL_ARB_vertex_buffer_object." << std::endl;
}
glslSupported = ext.isSupported("GL_ARB_vertex_program") && ext.isSupported("GL_ARB_fragment_program");
if(glslSupported)
{
std::cout << "Video card supports GLSL." << std::endl;
// compile shaders and create GLSL program
// If failed to create GLSL, reset flag to false
glslSupported = initGLSL();
}
else
{
std::cout << "[WARNING] Video card does NOT support GLSL." << std::endl;
}
// load BMP image
texId = loadTexture("earth2048.bmp", true);
// the last GLUT call (LOOP)
// window will be shown and display callback is triggered by events
// NOTE: this call never return main().
glutMainLoop(); // Start GLUT event-processing loop
return 0;
}
static void displayHelper() {
pThis->displayCB();
}
static void reshapeHelper(int w, int h) {
pThis->reshapeCB(w,h);
}
};
int main(int argc, char **argv) {
Test t(0);
t.helper(argc,argv);
}
我尝试过几次将代码放入类中,以确保没有遗漏任何东西,但我不知道我要去哪里。
答案 0 :(得分:0)
append
(和displayHelper
)创建尚未正确初始化的新reshapeHelper
对象。当您尝试利用它们来显示内容时(例如,通过调用Test
),您会得到很多未定义行为,因为您正在读取未初始化的值。也没有调用displayCB()
。
由于回调函数不提供传递自定义数据指针的方法,因此您必须诉诸使用initGLUT
的静态成员变量来存储指向类实例的指针
Test
您在构造函数中初始化的
static Test *pThis;
然后在您的回调中调用
pThis = this;
这意味着您随时只能实例化一个pThis->displayCB();
pThis->reshapeCB(w, h);
对象。
答案 1 :(得分:0)
请注意,每个 glut 窗口都有一个唯一的ID。当glutCreateWindow
创建窗口时,返回ID,glutGetWindow
可以在回调函数中获取ID。
由于使用的是c ++,因此可以使用std::map
来管理窗口对象。
创建一个** static * +属性(windowmap
),该属性将窗口ID与窗口对象(Test*
)相关联,并存储一个唯一的窗口ID(window_handle
) :
class Test {
static std::map<int, Test *> windowmap;
int window_handle = 0;
};
std::map<int, Test *> Test::windowmap;
在创建窗口时初始化属性window_handle
并将句柄与窗口对象的关联存储在地图中:
int handle = glutCreateWindow(argv[0]);
if (handle)
{
window_handle = handle;
windowmap[window_handle] = this;
}
添加一个静态方法,该方法将窗口对象返回给定的窗口ID:
static Test* GetWindow(int handle) {
return windowmap[handle];
}
使用该方法在回调中获取窗口对象。例如:
static void displayHelper() {
int handle = glutGetWindow();
if ( Test *window = GetWindow(handle) )
window->displayCB();
}
这是对代码的更改:
class Test {
public:
static std::map<int, Test *> windowmap;
int window_handle = 0;
Test (int i) {
// [...]
}
virtual ~Test() {
windowmap.erase( window_handle );
}
static Test* GetWindow(int handle) {
return windowmap[handle];
}
// [...]
int initGLUT(int argc, char **argv)
{
// [...]
int handle = glutCreateWindow(argv[0]);
if (handle)
{
window_handle = handle;
windowmap[window_handle] = this;
}
// [...]
}
// [...]
static void displayHelper() {
int handle = glutGetWindow();
if ( Test *window = GetWindow(handle) )
window->displayCB();
}
static void reshapeHelper(int w, int h) {
int handle = glutGetWindow();
if ( Test *window = GetWindow(handle) )
window->reshapeCB(w, h);
}
};
std::map<int, Test *> Test::windowmap;