碎片着色器莫名其妙的bahaviour [英] Fragment shader inexplicable bahaviour

查看:170
本文介绍了碎片着色器莫名其妙的bahaviour的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个C ++程序,我在这里绘制一个茶壶并应用照明。它本身很简单,但我也使用着色器。简单我是新的GLSL我只是试了一个简单的片段着色器,但屏幕输出是莫名的。

I have written a C++ program where I draw a teapot and apply lighting. It is itself simple, but I also use shaders. Simple I'm new with GLSL I just tried a simple fragment shader, but the screen output is inexplicable.

在此文件中,我在init方法中初始化glew,其中我还编译顶点和片段着色器。它们在vertex_shader和fragment_shader文件中。

In this file I initialize glew in the init method, where I also compile the vertex and fragment shader. They're in the "vertex_shader" and "fragment_shader" files.

你可能不认识的东西是什么是光和材料。它们只是一些结构,包含关于灯的所有信息。我测试了这些结构,所以我肯定工作按预期。当我声明material = BlackPlastic我只是设置为一个默认值用define指令定义。如果您认为问题存在,我也可以发布此代码。

The thing you may not recognize is what's Light and Material. They're just some structs containing all info about the lights. I've tested these struct so I'm sure the work as expected. When I declare material=BlackPlastic I just set it to a default value defined with the define directive. I may also post this code if you think that the problem is there.

#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>
#include <fstream>
#include <vector>
#include "utility.hpp"

#define MAX_DIM 1000

GLfloat width=600, height=800;
GLuint vertex_shader, fragment_shader;
GLuint program;
const char* vertex_shader_filename= "vertex_shader";
const char* fragment_shader_filename= "fragment_shader";
Light light;
Material material;

void init()
{    
    // Inizializzazione di GLEW
    glewInit();
    if(GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
    {
    cout << "Supporto GLSL" << endl;
    }

    // Lettura e compilazione del vertex shader
    GLchar* buffer= new GLchar[MAX_DIM];
    ifstream stream;
    streamsize count;
    stream.open(vertex_shader_filename);
    stream.read(buffer,MAX_DIM);
    count= stream.gcount();
    stream.close();
    vertex_shader= glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, (const GLchar**)&buffer, &count);
    glCompileShader(vertex_shader);

    // Lettura, inizializzazione ed esecuzione del fragment shader
    stream.open(fragment_shader_filename);
    stream.read(buffer,MAX_DIM);
    count= stream.gcount();
    stream.close();
    fragment_shader= glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, (const GLchar**)&buffer, &count);
    glCompileShader(fragment_shader);
    delete[] buffer;

    // Creazione del programma

    program= glCreateProgram();
    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);
    glLinkProgram(program);
    glUseProgram(program);

    // Inizializzazione materiale e luce
    material= BlackPlastic;
    light= {vector<GLfloat>{-2,2,2,1} ,vector<GLfloat>{1,1,1,1},vector<GLfloat>{1,1,1,1},vector<GLfloat>{1,1,1,1} };
}

void display()
{
    glEnable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45,width/height,1,1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0,0,-100,0,0,0,0,1,0);

    // Illuminazione
    glShadeModel(GL_SMOOTH);
    material.apply(); // This just causes glMaterialfv to be called for the ambient, diffuse, specular and shininess values.
    light.apply(); // This just causes glLightfv to be called for the ambient, diffuse and specular values
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);

    // Rendering
    glClearColor(0.8,0.8,0.8,1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glutSolidTeapot(10);
    glutSwapBuffers();
}

void reshape(int w, int h)
{
    width=w;
    height=h;
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(500,500);
    glutCreateWindow("test");
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    init();
    glutMainLoop();
    return 0;
}



我不认为顶点着色器会导致任何问题,分配颜色并正确计算位置。片段着色器显然是正确的,这是唯一执行的指令:

I don't think that the vertex shader is causing any problem, it just assigns the color and calculate the position, correctly. Also the fragment shader is apparently correct, this is the only instruction executed:

gl_FragColor = gl_Color;

如果我这样做,我只看到一个白色的茶壶。如果改为将此值更改为任何颜色:

If I do this I just see a white teapot. If instead I change this value to a whatever color:

gl_FragColor = vec4{0,0,1,1};

我得到的茶壶有正确的颜色:黑色塑料。我不知道为什么,我不应用照明这里,我应该计算它。

I get the teapot with the right color: black plastic. And I don't know why, I don't apply lighting here, I should calculate it.

我说明我执行了相同的程序,但没有应用着色器,我得到了茶壶的颜色。

I precisate that I executed the same identical program but without applying the shaders, and I got the teapot to have the right color.

推荐答案

首先,你要将固定函数管道与较新的东西混合。这是一个真正的不好的做法,因为它可以引起很多问题,因为你不知道在后台是怎么回事。

First off all you are mixing the fixed function pipeline with "the newer stuff". This is a real bad practice because it could couse a lot of issues because you don't really know what is going on in background.

如果你想有真正的照明与漫反射着色器,你必须自己计算漫反射颜色。很久以前,我最后一次使用ffp,所以我搜索了一些使用它的着色器:

If you want to have real lighting with diffuse shaders you have to calculate the diffuse color on your own. It's a long time ago i used the ffp the last time so i searched for some shaders wich use it:

顶点着色器

varying vec3 normal;
varying vec3 v;
varying vec3 lightvec;
void main(void)
{
    normal      = normalize(gl_NormalMatrix * gl_Normal);
    v           = vec3(gl_ModelViewMatrix * gl_Vertex);
    lightvec    = normalize(gl_LightSource[0].position.xyz - v);
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Fragment-Shader
$ b

Fragment-Shader

varying vec3 normal;
varying vec3 v;
varying vec3 lightvec;

void main(void)
{
   vec3 Eye          = normalize(-v);
   vec3 Reflected    = normalize( reflect( -lightvec, normal )); 
   vec4 IAmbient     = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;
   vec4 IDiffuse     = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * max(dot(normal, lightvec), 0.0);
   vec4 ISpecular    = gl_LightSource[0].specular * gl_FrontMaterial.specular * pow(max(dot(Reflected, Eye), 0.0), gl_FrontMaterial.shininess);
   gl_FragColor      = gl_FrontLightModelProduct.sceneColor + IAmbient + IDiffuse + ISpecular;
}

这篇关于碎片着色器莫名其妙的bahaviour的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆