ПрограммированиеФорумГрафика

Ошибка в шейдере

Страницы: 1 2 Следующая »
#0
1:29, 24 авг 2013

В общем написал шейдер для расчета освещения по Фонгу, но где-то внутри затаилась ошибка, которую я просто не вижу..

Вот эти 2 строчки, записывают в переменную location значение -1, а это значит, что шейдер написан неверно, но почему понять не могу.

GLint location = glGetAttribLocation(shader, "vertex.normal");
GLint location = glGetUniformLocation(shader, "light.coord");

Вершинный шейдер:

attribute struct Vertex {
  vec3 coord;
  vec3 color;
  vec3 normal;
  //vec2 textureCoord;
} vertex;

uniform struct Camera {
  mat4 matrix;
  vec3 coord;
} camera;

uniform struct Light {
  vec3 coord;
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec3 attenuation;
} light;

uniform struct Material {
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec4 emission;
  float shininess;
} material;

attribute vec3 lightDirection;
attribute vec3 viewDirection;
attribute float distance;

void main(void) {
  gl_Position = camera.matrix*vec4(vertex.coord, 1.0);

  lightDirection = normalize(light.coord - vertex.coord);
  viewDirection = normalize(camera.coord - vertex.coord);
  distance = length(lightDirection);
}

Фрагментный шейдер:

attribute struct Vertex {
  vec3 coord;
  vec3 color;
  vec3 normal;
  //vec2 textureCoord;
} vertex;

uniform struct Light {
  vec3 coord;
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec3 attenuation;
} light;

uniform struct Material {
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec4 emission;
  float shininess;
} material;

attribute vec3 lightDirection;
attribute vec3 viewDirection;
attribute float distance;

void main(void) {
  vertex.color = vec3(0.0, 0.0, 1.0);
  gl_FragColor = vec4(vertex.color, 1.0);

  float attenuation = 1.0/(light.attenuation[0] + light.attenuation[1]*distance + light.attenuation[2]*distance*distance);
  gl_FragColor = material.emission;
  gl_FragColor += material.ambient*light.ambient*attenuation;
  float NdotL = max(dot(vertex.normal, lightDirection), 0.0);
  gl_FragColor += material.diffuse*light.diffuse*NdotL*attenuation;
  float RdotVpow = max(pow(dot(reflect(-lightDirection, vertex.normal), viewDirection), material.shininess), 0.0);
  gl_FragColor += material.specular*light.specular*RdotVpow*attenuation;

  //gl_FragColor = vec4(vertex.color, 1.0);
}
#1
7:46, 24 авг 2013

ialexbr
Ты не передаешь нормаль в пиксельный шейдер.

#2
10:56, 24 авг 2013

Какие могут быть атрибуты во фрагментном шейдере?! Я даже не пойму, как у тебя такое компилируется. Атрибуты - это значения, уникальные для каждой вершины. Если тебе нужно передать какую-то информацию из вершинного шейдера во фрагментный, используй varying. В вершинном шейдере записываешь в эту varying переменную, а во фрагментном шейдере достаёшь, но уже интерполированные по полигону данные.
То в обоих шейдерах это

attribute vec3 lightDirection;
attribute vec3 viewDirection;
attribute float distance;

заменяешь на это

varying vec3 lightDirection;
varying vec3 viewDirection;
varying float distance;

Во фрагментном шейдере все атрибуты выкини. И если я ничего не упустил при беглом просмотре, то должно работать.

А про нормаль тебе уже сказали. В шейдере она не используется, поэтому оптимизатор её и выкинул и ты получаешь -1.

#3
18:51, 24 авг 2013

Теперь понял. Вот переделал, теперь оптимизатор ничего не выкидывает:

Вершинный шейдер

attribute struct Vertex {
  vec3 coord;
  vec3 normal;
} vertex;

uniform struct Camera {
  mat4 matrix;
  vec3 coord;
} camera;

uniform struct Light {
  vec3 coord;
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec3 attenuation;
} light;

varying vec3 vertex_normal;
varying vec3 lightDirection;
varying vec3 viewDirection;
varying float distance;

void main(void) {
  gl_Position = camera.matrix*vec4(vertex.coord, 1.0);

  vertex_normal = normalize(vertex.normal);
  lightDirection = normalize(light.coord - vertex.coord);
  viewDirection = normalize(camera.coord - vertex.coord);
  distance = length(lightDirection);
}

Фрагментный шейдер:

uniform struct Light {
  vec3 coord;
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec3 attenuation;
} light;

uniform struct Material {
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec4 emission;
  float shininess;
} material;

varying vec3 vertex_normal;
varying vec3 lightDirection;
varying vec3 viewDirection;
varying float distance;

void main(void) {
  //float attenuation = 1.0/(light.attenuation[0] + light.attenuation[1]*distance + light.attenuation[2]*distance*distance);
  //gl_FragColor = material.emission + material.ambient*light.ambient*attenuation;
  //float NdotL = max(dot(vertex_normal, lightDirection), 0.0);
  //gl_FragColor += material.diffuse*light.diffuse*NdotL*attenuation;
  //float RdotVpow = max(pow(dot(reflect(-lightDirection, vertex_normal), viewDirection), material.shininess), 0.0);
  //gl_FragColor += material.specular*light.specular*RdotVpow*attenuation;

  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}

Но появилась пара вопросов:
1) Можно ли как-то напрямую записывать данные в varying переменную из программы? А не сначала в attribute, а потом из нее в varying.
2) Данные в varying переменной интерполируются между вершинами в фрагментном шейдере. Но если мне это не надо делать (например с нормалями, они же одинаковые для всего полигона), тогда как быть? Конечно можно забить на это и оставить так, но все же не хочется, чтобы тратилось время на интерполирование, пусть оно маленькое, но оно тратится..

#4
19:34, 24 авг 2013

ialexbr
> тогда как быть?

Матчасть нужно учить, матчасть... :)

#5
20:04, 24 авг 2013

ialexbr
если нормали одинаковые, можно передать как uniform, но тогда тебе придется еще написать шейдер для нормалей, которые не одинаковы :) а еще надо трансформировать нормаль (поворачивать) разве нет? передавай как это делают обычно, через varying и не трать время зря, лучше напиши что-нибудь полезное)

#6
21:03, 24 авг 2013

ialexbr
1) Для этого есть uniform. varying выполняет иную функцию.
2) Экономия на спичках.

#7
22:42, 26 авг 2013

bool
> а еще надо трансформировать нормаль (поворачивать) разве нет?
Да это верно :)

#8
20:39, 17 сен 2013

Что-то снова не могу понять, почему оптимизатор выкидывает переменные..

glGetAttribLocation(shader, "vertex.position") возвращает -1


Вершинный шейдер:

attribute struct Vertex {
  vec3 position;
  vec2 textureCoord;
  vec3 normal;
} vertex;

uniform struct Camera {
  mat4 matrix;
  vec3 position;
} camera;

uniform struct Light {
  vec3 position;
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec3 attenuation;
} light;

varying vec2 textureCoord;
varying vec3 vertex_normal;
varying vec3 lightDirection;
varying vec3 viewDirection;

void main(void) {
  gl_Position = camera.matrix*vec4(vertex.position, 1.0);
  textureCoord = vertex.textureCoord;
  vertex_normal = vec3(camera.matrix*vec4(vertex.normal, 1.0));
  viewDirection = normalize(camera.position - vertex.position);
  lightDirection = normalize(light.position - vertex.position);
}

Фрагментный шейдер:

uniform sampler2D Texture;

uniform struct Light {
  vec3 position;
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec3 attenuation;
} light;

uniform struct Material {
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec4 emission;
  float shininess;
} material;

varying vec2 textureCoord;
varying vec3 vertex_normal;
varying vec3 lightDirection;
varying vec3 viewDirection;

void main(void) {
  gl_FragColor = material.emission + material.ambient*light.ambient*light.attenuation;

  float NdotL = max(dot(vertex_normal, lightDirection), 0.0);
  gl_FragColor += material.diffuse*light.diffuse*NdotL*light.attenuation;

  float RdotVpow = max(pow(dot(reflect(-lightDirection, vertex_normal), viewDirection), material.shininess), 0.0);
  gl_FragColor += material.specular*light.specular*RdotVpow*light.attenuation;

  gl_FragColor *= texture(Texture, textureCoord);
}
#9
21:29, 17 сен 2013

ialexbr

Я бы не стал передавать Vertex как структуру...

#10
15:39, 18 сен 2013

innuendo
А как лучше?

#11
15:51, 18 сен 2013

attribute vec3 position;
attribute  vec2 textureCoord;
attribute  vec3 normal;


как-то так

#12
22:29, 18 сен 2013

innuendo
А чем это хуже структуры?

#13
22:35, 18 сен 2013

ialexbr
Ты попробуй и расскажешь.

#14
22:20, 19 сен 2013

Попробовал, cнова glGetAttribLocation(shader, "in_vertex_position") возвращает -1!!


Вершинный шейдер:

#version 330 core

attribute  vec3  in_vertex_position;
attribute  vec2  in_vertex_textureCoord;
attribute  vec3  in_vertex_normal;
uniform    mat4  camera_matrix;
uniform    vec3  camera_position;
uniform    vec3  light_position;

varying    vec2  vertex_textureCoord;
varying    vec3  vertex_normal;
varying    vec3  light_direction;
varying    vec3  view_direction;

void main(void) {
  gl_Position = camera_matrix*vec4(in_vertex_position, 1.0);
  vertex_textureCoord = in_vertex_textureCoord;
  vertex_normal = vec3(camera_matrix*vec4(in_vertex_normal, 1.0));
  light_direction = normalize(light_position - in_vertex_position);
  view_direction = normalize(camera_position - in_vertex_position);
}


Фрагментный шейдер:

#version 330 core

varying    vec2    vertex_textureCoord;
varying    vec3    vertex_normal;
varying    vec3    light_direction;
varying    vec3    view_direction;

uniform    sampler2D  Texture;
uniform    vec4    light_ambient;
uniform    vec4    light_diffuse;
uniform    vec4    light_specular;
uniform    vec3    light_attenuation;
uniform    vec4    material_ambient;
uniform    vec4    material_diffuse;
uniform    vec4    material_specular;
uniform    vec4    material_emission;
uniform    float    material_shininess;

void main(void) {
  gl_FragColor = material_emission + material_ambient*light_ambient*light_attenuation;

  float NdotL = max(dot(vertex_normal, light_direction), 0.0);
  gl_FragColor += material_diffuse*light_diffuse*NdotL*light_attenuation;

  float RdotVpow = max(pow(dot(reflect(-light_direction, vertex_normal), view_direction), material_shininess), 0.0);
  gl_FragColor += material_specular*light_specular*RdotVpow*light_attenuation;
  
  gl_FragColor *= texture(Texture, vertex_textureCoord);
}
Страницы: 1 2 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.