Я новичок в OpenGL и изучаю его с помощью SharpGL, который является простым связыванием C# с функциями OpenGL. Я пытаюсь использовать простейшие шейдеры вершин и фрагментов. Когда фрагментарный шейдер генерирует вывод сам по себе, все в порядке, но когда он пытается использовать данные, полученные из вершинного шейдера, есть только черный экран. Шейдеры успешно скомпилированы и связаны с программой. OpenGL не возвращал ошибок. После тонны статей, примеров и руководств я до сих пор не знаю, почему это происходит. Вот вершинный шейдер.Не удается передать цвет от вершинного шейдера до фрагмента шейдера
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color;
out vec3 rgb;
void main()
{
rgb = vec3(1.0, 0.5, 0.5);
gl_Position = vec4(position, 1.0);
}
Фрагмент шейдеры:
#version 330
in vec3 rgb;
out vec3 outColor;
void main()
{
//outColor = rgb; // black display
outColor = vec3(1.0, 0.0, 0.4); // works fine
}
Вот код инициализации:
gl.GenVertexArrays(1, arrayBuffer);
gl.BindVertexArray(arrayBuffer[0]);
gl.GenBuffers(1, pointsBuffer);
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, pointsBuffer[0]);
gl.BufferData(OpenGL.GL_ARRAY_BUFFER, triangle, OpenGL.GL_STATIC_DRAW);
gl.GenBuffers(1, colorsBuffer);
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, colorsBuffer[0]);
gl.BufferData(OpenGL.GL_ARRAY_BUFFER, colors, OpenGL.GL_STATIC_DRAW);
И, наконец, вот что случилось на каждой итерации:
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
gl.UseProgram(program.Id);
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, pointsBuffer[0]);
gl.EnableVertexAttribArray(0);
gl.VertexAttribPointer(0, 3, OpenGL.GL_FLOAT, false, 0, IntPtr.Zero);
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, colorsBuffer[0]);
gl.EnableVertexAttribArray(1);
gl.VertexAttribPointer(1, 3, OpenGL.GL_FLOAT, false, 0, IntPtr.Zero);
gl.DrawArrays(OpenGL.GL_TRIANGLES, 0, 12);
gl.DisableVertexAttribArray(0);
gl.DisableVertexAttribArray(1);
UP D 1. Вот данные, переданные буферам.
private float[] triangle = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
};
private float[] colors = {
1.0f, 0.0f, 0.0f,
0.5f, 1.0f, 0.0f,
0.0f, 0.5f, 0.0f
};
private uint[] arrayBuffer = new uint[1];
private uint[] pointsBuffer = new uint[1];
private uint[] colorsBuffer = new uint[1];
UPD 2 Вот шейдеры компиляции кода
private uint CompileProgram(OpenGL gl, List<ShaderMetadata> shaders)
{
var program = gl.CreateProgram();
shaders.ForEach(shader => gl.AttachShader(program, CompileShader(gl, shader.Path, shader.Mode)));
gl.LinkProgram(program);
var status = ProgramErrorInfo(gl, program);
if (!String.IsNullOrEmpty(status))
{
throw new ArgumentException(status);
}
return program;
}
private uint CompileShader(OpenGL gl, string path, uint kind)
{
using (var fs = new FileStream(path, FileMode.Open))
{
using (var reader = new StreamReader(fs))
{
var program = reader.ReadToEnd();
var id = gl.CreateShader(kind);
gl.ShaderSource(id, program);
gl.CompileShader(id);
var status = ShaderErrorInfo(gl, id);
if (!String.IsNullOrEmpty(status))
{
throw new ArgumentException(status);
}
return id;
}
}
}
private string ShaderErrorInfo(OpenGL gl, uint shaderId)
{
StringBuilder builder = new StringBuilder(2048);
gl.GetShaderInfoLog(shaderId, 2048, IntPtr.Zero, builder);
return builder.ToString();
}
private string ProgramErrorInfo(OpenGL gl, uint programId)
{
StringBuilder builder = new StringBuilder(2048);
gl.GetProgramInfoLog(programId, 2048, IntPtr.Zero, builder);
return builder.ToString();
}
UPD 3 А вот как компилятор вызывается
var programId = CompileProgram(gl, new List<ShaderMetadata>
{
new ShaderMetadata(
@"vertex.shader",
OpenGL.GL_VERTEX_SHADER),
new ShaderMetadata(
@"fragment.shader",
OpenGL.GL_FRAGMENT_SHADER)
});
Я не вижу ваш код для создания шейдерной программы. – JojOatXGME
@JojOatXGME Присоединено к UPD 2 и 3 –
Простите мое незнание с помощью C#, но как массив достаточно большой, чтобы содержать одно целое без знака, которое должно хранить все эти данные вершин? Каждый компонент 'float' имеет тот же размер, что и одно целое. –