В общем написал шейдер для расчета освещения по Фонгу, но где-то внутри затаилась ошибка, которую я просто не вижу..
Вот эти 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); }
ialexbr
Ты не передаешь нормаль в пиксельный шейдер.
Какие могут быть атрибуты во фрагментном шейдере?! Я даже не пойму, как у тебя такое компилируется. Атрибуты - это значения, уникальные для каждой вершины. Если тебе нужно передать какую-то информацию из вершинного шейдера во фрагментный, используй varying. В вершинном шейдере записываешь в эту varying переменную, а во фрагментном шейдере достаёшь, но уже интерполированные по полигону данные.
То в обоих шейдерах это
attribute vec3 lightDirection;
attribute vec3 viewDirection;
attribute float distance;заменяешь на это
varying vec3 lightDirection;
varying vec3 viewDirection;
varying float distance;Во фрагментном шейдере все атрибуты выкини. И если я ничего не упустил при беглом просмотре, то должно работать.
А про нормаль тебе уже сказали. В шейдере она не используется, поэтому оптимизатор её и выкинул и ты получаешь -1.
Теперь понял. Вот переделал, теперь оптимизатор ничего не выкидывает:
Вершинный шейдер
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 переменной интерполируются между вершинами в фрагментном шейдере. Но если мне это не надо делать (например с нормалями, они же одинаковые для всего полигона), тогда как быть? Конечно можно забить на это и оставить так, но все же не хочется, чтобы тратилось время на интерполирование, пусть оно маленькое, но оно тратится..
ialexbr
> тогда как быть?
Матчасть нужно учить, матчасть... :)
ialexbr
если нормали одинаковые, можно передать как uniform, но тогда тебе придется еще написать шейдер для нормалей, которые не одинаковы :) а еще надо трансформировать нормаль (поворачивать) разве нет? передавай как это делают обычно, через varying и не трать время зря, лучше напиши что-нибудь полезное)
ialexbr
1) Для этого есть uniform. varying выполняет иную функцию.
2) Экономия на спичках.
bool
> а еще надо трансформировать нормаль (поворачивать) разве нет?
Да это верно :)
Что-то снова не могу понять, почему оптимизатор выкидывает переменные..
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);
}ialexbr
Я бы не стал передавать Vertex как структуру...
innuendo
А как лучше?
attribute vec3 position;
attribute vec2 textureCoord;
attribute vec3 normal;
как-то так
innuendo
А чем это хуже структуры?
ialexbr
Ты попробуй и расскажешь.
Попробовал, 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);
}Тема в архиве.