c++ - 红皮书毛皮示例不渲染毛皮 (Linux/nvidia gtx675mx)

标签 c++ linux opengl nvidia

我试图让红皮书(第 8 版)第 10 章 Fur 示例在我的 Ubuntu 14.04 笔记本电脑上使用 Nvidia GTX675MX

我已经更改了代码以使用 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;
}

最佳答案

我添加

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,现在着色器可以编译并链接。

关于c++ - 红皮书毛皮示例不渲染毛皮 (Linux/nvidia gtx675mx),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24982023/

相关文章:

c++ - 在 C++ 中使用 Perl + Regex 将#define 更改为#undef

linux - Apache 2.4 命中 rlimit_nproc : hidden processes?

c++ - 使用 SDL 加载 OpenGL 纹理

windows - Linux 和 Windows XP 上的 OpenGL 性能差异

c++ - 从 stringstream 获取所有内容

c++ - c++中 'char()'和 'char'有什么区别

c++ - 如何随机初始化常量数据成员?

linux - 在保护我的网络服务器(rpi)免受外部 ssh 登录的影响后,我在我的计算机上发现了这个 perl 脚本。有人能告诉我它有什么作用吗?

linux - sed命令删除其中包含特殊字符的起始模式匹配

opengl - 如何使用GLSL计算指定颜色像素的数量?