我试图通过Nvidia GTX675MX获得红皮书(第8版)第10章毛皮示例,以便在我的Ubuntu 14.04笔记本电脑上工作
我已将代码更改为使用SDL2和glm,但其他所有内容都与红皮书中的内容相同。
代码编译并运行,但3d对象不是毛发着色。
任何人都可以发现任何错误,或者我的GPU根本无法完成任务吗?
(完整来源:http://openme.gl/redbook_chapter_10_fur.zip)
#define GLM_FORCE_RADIANS
#include <string>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <SDL2/SDL.h>
#include "vermilion.h"
#include "vutils.h"
#include "vbm.h"
#define BUFFER_OFFSET(x) ((const void*) (x))
#define PROGRAM_NAME "Red Book - Chapter 10 - Fur"
void Initialize();
void Display();
void Finalize(void);
void Reshape(int width, int height);
float aspect;
GLuint base_prog;
GLuint fur_prog;
GLuint fur_texture;
VBObject object;
GLint fur_model_matrix_pos;
GLint fur_projection_matrix_pos;
GLint base_model_matrix_pos;
GLint base_projection_matrix_pos;
void Initialize()
{
base_prog = glCreateProgram();
static const char base_vs_source[] =
"#version 410\n"
"\n"
"layout (location = 0) in vec4 position_in;\n"
"layout (location = 1) in vec3 normal_in;\n"
"layout (location = 2) in vec2 texcoord_in;\n"
"\n"
"uniform mat4 model_matrix;\n"
"uniform mat4 projection_matrix;\n"
"\n"
"out VS_FS_VERTEX\n"
"{\n"
" vec3 normal;\n"
"} vertex_out;\n"
"\n"
"void main(void)\n"
"{\n"
" vertex_out.normal = normal_in;\n"
" gl_Position = projection_matrix * (model_matrix * position_in);\n"
"}\n";
static const char base_fs_source[] =
"#version 410\n"
"\n"
"layout (location = 0) out vec4 color;\n"
"\n"
"in VS_FS_VERTEX\n"
"{\n"
" vec3 normal;\n"
"} vertex_in;\n"
"\n"
"void main(void)\n"
"{\n"
" vec3 normal = vertex_in.normal;\n"
" color = vec4(0.2, 0.1, 0.5, 1.0) * (0.2 + pow(abs(normal.z), 4.0)) + vec4(0.8, 0.8, 0.8, 0.0) * pow(abs(normal.z), 137.0);\n"
"}\n";
vglAttachShaderSource(base_prog, GL_VERTEX_SHADER, base_vs_source);
vglAttachShaderSource(base_prog, GL_FRAGMENT_SHADER, base_fs_source);
glLinkProgram(base_prog);
glUseProgram(base_prog);
base_model_matrix_pos = glGetUniformLocation(base_prog, "model_matrix");
base_projection_matrix_pos = glGetUniformLocation(base_prog, "projection_matrix");
fur_prog = glCreateProgram();
static const char fur_vs_source[] =
"#version 410\n"
"\n"
"layout (location = 0) in vec4 position_in;\n"
"layout (location = 1) in vec3 normal_in;\n"
"layout (location = 2) in vec2 texcoord_in;\n"
"\n"
"out VS_GS_VERTEX\n"
"{\n"
" vec3 normal;\n"
" vec2 tex_coord;\n"
"} vertex_out;\n"
"\n"
"void main(void)\n"
"{\n"
" vertex_out.normal = normal_in;\n"
" vertex_out.tex_coord = texcoord_in;\n"
" gl_Position = position_in;\n"
"}\n";
static const char fur_gs_source[] =
"#version 410\n"
"\n"
"layout (triangles) in;\n"
"layout (triangle_strip, max_vertices = 240) out;\n"
"\n"
"uniform mat4 model_matrix;\n"
"uniform mat4 projection_matrix;\n"
"\n"
"uniform int fur_layers = 30;\n"
"uniform float fur_depth = 5.0;\n"
"\n"
"in VS_GS_VERTEX\n"
"{\n"
" vec3 normal;\n"
" vec2 tex_coord;\n"
"} vertex_in[];\n"
"\n"
"out GS_FS_VERTEX\n"
"{\n"
" vec3 normal;\n"
" vec2 tex_coord;\n"
" flat float fur_strength;\n"
"} vertex_out;\n"
"\n"
"void main(void)\n"
"{\n"
" int i, layer;\n"
" float disp_delta = 1.0 / float(fur_layers);\n"
" float d = 0.0;\n"
" vec4 position;\n"
"\n"
" for (layer = 0; layer < fur_layers; layer++)\n"
" {\n"
" for (i = 0; i < gl_in.length(); i++) {\n"
" vec3 n = vertex_in[i].normal;\n"
" vertex_out.normal = n;\n"
" vertex_out.tex_coord = vertex_in[i].tex_coord;\n"
" vertex_out.fur_strength = 1.0 - d;\n"
" position = gl_in[i].gl_Position + vec4(n * d * fur_depth, 0.0);\n"
" gl_Position = projection_matrix * (model_matrix * position);\n"
" EmitVertex();\n"
" }\n"
" d += disp_delta;\n"
" EndPrimitive();\n"
" }\n"
"}\n";
static const char fur_fs_source[] =
"#version 410\n"
"\n"
"layout (location = 0) out vec4 color;\n"
"\n"
"uniform sampler2D fur_texture;\n"
"uniform vec4 fur_color = vec4(0.8, 0.8, 0.9, 1.0);\n"
"\n"
"in GS_FS_VERTEX\n"
"{\n"
" vec3 normal;\n"
" vec2 tex_coord;\n"
" flat float fur_strength;\n"
"} fragment_in;\n"
"\n"
"void main(void)\n"
"{\n"
" vec4 rgba = texture(fur_texture, fragment_in.tex_coord);\n"
" float t = rgba.a;\n"
" t *= fragment_in.fur_strength;\n"
" color = fur_color * vec4(1.0, 1.0, 1.0, t);\n"
"}\n";
vglAttachShaderSource(fur_prog, GL_VERTEX_SHADER, fur_vs_source);
vglAttachShaderSource(fur_prog, GL_GEOMETRY_SHADER, fur_gs_source);
vglAttachShaderSource(fur_prog, GL_FRAGMENT_SHADER, fur_fs_source);
glLinkProgram(fur_prog);
glUseProgram(fur_prog);
fur_model_matrix_pos = glGetUniformLocation(fur_prog, "model_matrix");
fur_projection_matrix_pos = glGetUniformLocation(fur_prog, "projection_matrix");
glGenTextures(1, &fur_texture);
unsigned char * tex = (unsigned char *)malloc(1024 * 1024 * 4);
memset(tex, 0, 1024 * 1024 * 4);
int n, m;
for (n = 0; n < 256; n++)
{
for (m = 0; m < 1270; m++)
{
int x = rand() & 0x3FF;
int y = rand() & 0x3FF;
tex[(y * 1024 + x) * 4 + 0] = (rand() & 0x3F) + 0xC0;
tex[(y * 1024 + x) * 4 + 1] = (rand() & 0x3F) + 0xC0;
tex[(y * 1024 + x) * 4 + 2] = (rand() & 0x3F) + 0xC0;
tex[(y * 1024 + x) * 4 + 3] = n;
}
}
glBindTexture(GL_TEXTURE_2D, fur_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
free(tex);
object.LoadFromVBM("ninja.vbm", 0, 1, 2);
}
void Display()
{
float t = float(SDL_GetTicks() & 0x3FFF) / float(0x3FFF);
static const glm::vec3 X(1.0f, 0.0f, 0.0f);
static const glm::vec3 Y(0.0f, 1.0f, 0.0f);
static const glm::vec3 Z(0.0f, 0.0f, 1.0f);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 p(glm::frustum(-1.0f, 1.0f, aspect, -aspect, 1.0f, 5000.0f));
glm::mat4 m;
m = glm::mat4(glm::translate(glm::mat4(1.0),glm::vec3(0.0f,
0.0f,
/* 100.0f * sinf(6.28318531f * t)*/ - 130.0f)) *
//glm::rotation(360.0f * t, X) *
glm::rotate(glm::mat4(1.0),36.0f * t * 1.0f, Y) *
glm::rotate(glm::mat4(1.0),18.0f, Z) *
glm::translate(glm::mat4(1.0),glm::vec3(0.0f, -80.0f, 0.0f)));
glUseProgram(base_prog);
glUniformMatrix4fv(base_model_matrix_pos, 1, GL_FALSE, glm::value_ptr(m));
glUniformMatrix4fv(base_projection_matrix_pos, 1, GL_FALSE, glm::value_ptr(p));
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
object.Render();
glUseProgram(fur_prog);
glUniformMatrix4fv(fur_model_matrix_pos, 1, GL_FALSE, glm::value_ptr(m));
glUniformMatrix4fv(fur_projection_matrix_pos, 1, GL_FALSE, glm::value_ptr(p));
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE);
object.Render();
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
}
void Finalize(void)
{
glUseProgram(0);
glDeleteProgram(fur_prog);
}
void Reshape(int width, int height)
{
glViewport(0, 0 , width, height);
aspect = float(height) / float(width);
}
int main(int argc, char *argv[]){
SDL_Window *mainwindow; /* Our window handle */
SDL_GLContext maincontext; /* Our opengl context handle */
if (SDL_Init(SDL_INIT_VIDEO) < 0) { /* Initialize SDL's Video subsystem */
std::cout << "Unable to initialize SDL";
return 1;
}
/* Request opengl 4.4 context. */
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
/* Turn on double buffering with a 24bit Z buffer.
* You may need to change this to 16 or 32 for your system */
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
/* Create our window centered at 512x512 resolution */
mainwindow = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if (!mainwindow){ /* Die if creation failed */
std::cout << "SDL Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
/* Create our opengl context and attach it to our window */
maincontext = SDL_GL_CreateContext(mainwindow);
GLenum rev;
glewExperimental = GL_TRUE;
rev = glewInit();
if (GLEW_OK != rev){
std::cout << "Error: " << glewGetErrorString(rev) << std::endl;
exit(1);
} else {
std::cout << "GLEW Init: Success!" << std::endl;
}
/* This makes our buffer swap syncronized with the monitor's vertical refresh */
SDL_GL_SetSwapInterval(1);
bool quit=false;
Initialize();
Reshape(512,512);
SDL_Event event;
while(!quit){
Display();
SDL_GL_SwapWindow(mainwindow);
while( SDL_PollEvent( &event ) ){
if( event.type == SDL_QUIT ){
quit = true;
}
if(event.type ==SDL_WINDOWEVENT){
if(event.window.event = SDL_WINDOWEVENT_SIZE_CHANGED){
int w,h;
SDL_GetWindowSize(mainwindow,&w,&h);
Reshape(w,h);
}
}
}
}
Finalize();
/* Delete our opengl context, destroy our window, and shutdown SDL */
SDL_GL_DeleteContext(maincontext);
SDL_DestroyWindow(mainwindow);
SDL_Quit();
return 0;
}
答案 0 :(得分:1)
我添加了
glGetProgramInfoLog(fur_prog, sizeof(buffer), &length, buffer);
std::cout << length << std::endl;
std::cout << buffer << std::endl;
得到了
Geometry info
-------------
(0) : error C6033: Hardware limitation reached, can only emit 146 vertices of this size
将max_vertices更改为146,现在着色器编译并链接。