我目前正在尝试通过OpenGL SuperBible(6E)学习OpenGL。但是,我不是使用作者编写的窗口类,而是尝试将这些示例应用到我自己的GLFW窗口环境中。
到目前为止,我已经能够自己重新创建许多示例,但我遇到了一个我无法开始工作的例子。
#include <sb6.h>
#include <math.h>
class singlepoint_app : public sb6::application
{
void init()
{
static const char title[] = "OpenGL SuperBible - Single Point";
sb6::application::init();
memcpy(info.title, title, sizeof(title));
}
virtual void startup()
{
static const char * vs_source[] =
{
"#version 410 core \n"
" \n"
"layout (location = 0) in vec4 offset; \n"
" \n"
"void main(void) \n"
"{ \n"
" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4( 0.25, 0.25, 0.5, 1.0)); \n"
" \n"
" // Add 'offset' to our hard-coded vertex position \n"
" gl_Position = vertices[gl_VertexID] + offset; \n"
"} \n"
};
static const char * fs_source[] =
{
"#version 410 core \n"
" \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.0, 0.8, 1.0, 1.0); \n"
"} \n"
};
program = glCreateProgram();
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
}
virtual void render(double currentTime)
{
static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, green);
glUseProgram(program);
GLfloat attrib[] = { (float)sin(currentTime) * 0.5f,
(float)cos(currentTime) * 0.6f,
0.0f, 0.0f };
glVertexAttrib4fv(0, attrib);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
virtual void shutdown()
{
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program);
}
private:
GLuint program;
GLuint vao;
};
DECLARE_MAIN(singlepoint_app)
#include "glew.h"
#include "glfw3.h"
#include "math.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
int main(void)
{
GLFWwindow* window;
if (!glfwInit())
{
exit(EXIT_FAILURE);
}
window = glfwCreateWindow(800, 600, "OpenGL - movingtri", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glewInit();
//begin OpenGL code from example movingtri.cpp
GLuint program;
GLuint vao;
static const char * vs_source[] =
{
"#version 410 core \n"
" \n"
"layout (location = 0) in vec4 offset; \n"
" \n"
"void main(void) \n"
"{ \n"
" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4( 0.25, 0.25, 0.5, 1.0)); \n"
" \n"
" // Add 'offset' to our hard-coded vertex position \n"
" gl_Position = vertices[gl_VertexID] + offset; \n"
"} \n"
};
static const char * fs_source[] =
{
"#version 410 core \n"
" \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.0, 0.8, 1.0, 1.0); \n"
"} \n"
};
program = glCreateProgram();
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// end of movingtri initialization
while (!glfwWindowShouldClose(window))
{
double currentTime = glfwGetTime();
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// begin rendering code from movingtri
static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, green);
glUseProgram(program);
GLfloat attrib[] = { (float)sin(currentTime) * 0.5f,
(float)cos(currentTime) * 0.6f,
0.0f, 0.0f };
glVertexAttrib4fv(0, attrib);
glDrawArrays(GL_TRIANGLES, 0, 3);
//end rendering code
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
我上面使用的相同复制和粘贴技术在SuperBible中处理了许多其他更复杂的示例。
我已经测试并修改了这段代码几个小时,但我只做了一个可能相关的观察:
如果我从此行中删除“+ offset”:
" gl_Position = vertices[gl_VertexID] + offset; \n"
然后出现三角形,但当然不会移动。
http://i.stack.imgur.com/deF3B.gif
答案 0 :(得分:1)
您需要从GLFW请求核心上下文。检查着色器编译和链接状态/日志也是一个好主意。
尝试这样的事情:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
char log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( -1 );
}
void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
GLuint LoadProgram( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
#define GLSL(version, shader) "#version " #version "\n" #shader
int main( int argc, char** argv )
{
if( !glfwInit() )
{
exit(EXIT_FAILURE);
}
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 1 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL - movingtri", NULL, NULL);
if( !window )
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
GLenum err = glewInit();
if( GLEW_OK != err )
{
cerr << "glewInit() failed: " << glewGetErrorString(err) << endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
const char* vert = GLSL
(
410 core,
layout (location = 0) in vec4 offset;
void main()
{
const vec4 vertices[] = vec4[]
(
vec4( 0.25, -0.25, 0.5, 1.0),
vec4(-0.25, -0.25, 0.5, 1.0),
vec4( 0.25, 0.25, 0.5, 1.0)
);
// Add 'offset' to our hard-coded vertex position
gl_Position = vertices[ gl_VertexID ] + offset;
}
);
const char* frag = GLSL
(
410 core,
out vec4 color;
void main()
{
color = vec4(0.0, 0.8, 1.0, 1.0);
}
);
GLuint program = LoadProgram( vert, NULL, frag );
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
while( !glfwWindowShouldClose(window) )
{
double currentTime = glfwGetTime();
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// begin rendering code from movingtri
static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, green);
glUseProgram(program);
GLfloat attrib[] =
{
(float)sin(currentTime) * 0.5f,
(float)cos(currentTime) * 0.6f,
0.0f,
0.0f
};
glVertexAttrib4fv(0, attrib);
glDrawArrays(GL_TRIANGLES, 0, 3);
//end rendering code
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
答案 1 :(得分:0)
这里也有同样的问题,但我确实有效。
顶点着色器:
layout (location = 1) in vec4 offset;
程序:
glVertexAttrib4fv(1, attrib);
所以我所做的就是将位置更改为1而不是0.其他大于0的数字也没问题。 我不知道为什么location = 0似乎被禁止用于除顶点位置之外的任何数据。
有人有想法吗?