В настоящее время я пытаюсь рисовать простые сетки, используя различные текстуры (используя C # и OpenTK).Я много читал о TextureUnit и привязках, и это моя текущая реализация (не работает должным образом):
private void ApplyOpaquePass()
{
GL.UseProgram(this.shaderProgram);
GL.CullFace(CullFaceMode.Back);
while (this.opaqueNodes.Count > 0)
Draw(this.opaqueNodes.Pop());
GL.UseProgram(0);
}
И мой метод отрисовки:
private void Draw(Assets.Model.Geoset geoset)
{
GL.ActiveTexture(TextureUnit.Texture1);
GL.BindTexture(TextureTarget.Texture2D, geoset.TextureId /*buffer id returned by GL.GenTextures*/ );
GL.Uniform1(GL.GetUniformLocation(this.shaderProgram, "Texture1"), 1 /*see note below*/ );
//Note: if I'm correct, it should be 1 when using TextureUnit.Texture1
// (2 for Texture2...), note that doesn't seem to work since no
// texture texture at all is sent to the shader, however a texture
// is shown when specifying any other number (0, 2, 3...)
// Draw vertices & indices buffers...
}
И мой код шейдера (этоне должно быть проблемой, так как с ультрафиолетовым отображением все в порядке):
uniform sampler2D Texture1;
void main(void)
{
gl_FragColor = texture2D(Texture1, gl_TexCoord[0].st);
}
В чем проблема:
Поскольку geoset.TextureId может варьироваться от одного геосета к другому, я ожидаю, что в шейдер будет отправлена другая текстура.
Вместо этого ко всем объектам (геосетям) всегда применяется одинаковая текстура.
Идеи:
Использование различных текстур для каждой текстуры (работает хорошо), но что произойдет, если у нас будет 2000 различных текстур?Если мое понимание верно, мы должны использовать несколько TextureUnit, только если мы хотим использовать несколько текстур одновременно в шейдере.
Сначала я подумал, что униформане может быть изменен после определения, но тест с логической формой сказал мне, что это действительно возможно.
private void Draw(Assets.Model.Geoset geoset)
{
GL.ActiveTexture(TextureUnit.Texture1);
GL.BindTexture(TextureTarget.Texture2D, geoset.TextureId);
GL.Uniform1(GL.GetUniformLocation(this.shaderProgram, "Texture1"), 1 );
//added line...
GL.Uniform1(GL.GetUniformLocation(this.shaderProgram, "UseBaseColor"), (geoset.Material.FilterMode == Assets.Model.Material.FilterType.Blend) ? 1: 0);
// Draw vertices & indices buffers...
}
Код шейдера:
uniform sampler2D Texture1;
uniform bool UseBaseColor;
void main(void)
{
gl_FragColor = texture2D(Texture1, gl_TexCoord[0].st);
if (UseBaseColor)
gl_FragColor = mix(vec4(0,1,1,1), gl_FragColor , gl_FragColor .a);
}
Этот код прекрасно работает, рисуянекоторый геосет с базовым цветом вместо прозрачности, который (должен?) доказывает, что форму можно изменить здесь.Почему это не работает с моими текстурами?
Должен ли я использовать разные шейдерные программы для каждого геосета?
Заранее спасибо за ваши ответы:)
С уважением,Брюс
РЕДАКТИРОВАТЬ: вот как я генерирую текстуры в рендере:
override public uint GenTexture(Bitmap bmp)
{
uint texture;
GL.GenTextures(1, out texture);
//I disabled this line because I now bind the texture before drawing a geoset
//Anyway, uncommenting this line doesn't show a better result
//GL.BindTexture(TextureTarget.Texture2D, texture);
System.Drawing.Imaging.BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
bmp.UnlockBits(data);
//temp settings
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
return texture;
}