Введение
У меня есть тестовое приложение, которое рисует следующее:
Левые треугольники нарисованы через:
GL.glBegin(GL.GL_TRIANGLES);
{
for (int i = 0; i < 50; i++)
{
GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
}
}
GL.glEnd();
Правильные треугольники нарисованы с помощью:
GL.glBindTexture(GL.GL_TEXTURE_2D, texture);
GL.glBegin(GL.GL_QUADS);
{
GL.glTexCoord2f(0, 1); GL.glVertex2f(0, 1);
GL.glTexCoord2f(0, 0); GL.glVertex2f(0, 0);
GL.glTexCoord2f(1, 0); GL.glVertex2f(1, 0);
GL.glTexCoord2f(1, 1); GL.glVertex2f(1, 1);
}
GL.glEnd();
Текстура отображается через FBO.
Проблема
Мне трудно заставить GL_TEXTURE_2D и GL_TEXTURE_3D играть вместе. Все прекрасно работает, пока я не раскомментирую следующий раздел кода:
GL.glEnable(GL.GL_TEXTURE_2D);
// GL.glEnable(GL.GL_TEXTURE_3D);
В результате я получаю следующее изображение (2D-текстура перестает работать):
Есть ли способ заставить 2D и 3D текстуры работать вместе? Мне нужно визуализировать 3D-текстуру в 2D-текстуру через FBO. Есть ли способ сделать это?
Полный исходный код
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics;
using ManOCL;
using Monobjc.OpenGL;
using TextureTarget = OpenTK.Graphics.OpenGL.TextureTarget;
namespace Test
{
class Program
{
static void InitViewport(INativeWindow wnd, IGraphicsContext ctx)
{
GL.glViewport(0, 0, wnd.Width, wnd.Height);
GL.glMatrixMode(GL.GL_PROJECTION);
GL.glLoadIdentity();
GL.glMatrixMode(GL.GL_MODELVIEW);
GL.glLoadIdentity();
Double aspect = 1;
if (wnd.Height > 0)
{
aspect = wnd.Width / (double)wnd.Height;
}
Double square = 2;
Double realWidth = square * aspect;
GL.glOrtho(-realWidth * 0.5, realWidth * 0.5, -square * 0.5, square * 0.5, -1, 1);
ctx.Update(wnd.WindowInfo);
}
static void InitGL(INativeWindow wnd, IGraphicsContext ctx)
{
GL.glShadeModel(GL.GL_SMOOTH);
GL.glEnable(GL.GL_TEXTURE_2D);
// GL.glEnable(GL.GL_TEXTURE_3D);
GL.glEnable(GL.GL_BLEND);
GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
GL.glDisable(GL.GL_DEPTH_TEST);
GL.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
GL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
static uint CreateTexture2D(Int32 width, Int32 height)
{
uint texture;
GL.glGenTextures(1, out texture);
GL.glBindTexture(GL.GL_TEXTURE_2D, texture);
GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, IntPtr.Zero);
GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP);
GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP);
GL.glBindTexture(GL.GL_TEXTURE_2D, 0);
return texture;
}
static uint CreateFBO()
{
uint fbo;
GL.glGenFramebuffers(1, out fbo);
return fbo;
}
[STAThread]
static void Main(string[] args)
{
Int32 strips = 32;
Int32 stripComponents = 6;
Random rand = new Random();
INativeWindow wnd = new OpenTK.NativeWindow(800, 600, "OpenGL", GameWindowFlags.Default, GraphicsMode.Default, DisplayDevice.Default);
IGraphicsContext ctx = new GraphicsContext(GraphicsMode.Default, wnd.WindowInfo);
wnd.Visible = true;
wnd.Resize += delegate { InitViewport(wnd, ctx); };
wnd.KeyPress += delegate(object sender, OpenTK.KeyPressEventArgs e) {
if (e.KeyChar == 'q')
{
wnd.Close();
}
else if (e.KeyChar == '=' || e.KeyChar == '+')
{
Size size = wnd.Size;
Point location = wnd.Location;
wnd.Location = new Point(location.X - 16, location.Y);
wnd.Size = new Size(size.Width + 32, size.Height + 32);
}
else if (e.KeyChar == '-')
{
Size size = wnd.Size;
Point location = wnd.Location;
wnd.Location = new Point(location.X + 16, location.Y + 44);
wnd.Size = new Size(size.Width - 32, size.Height - 32);
}
};
ctx.MakeCurrent(wnd.WindowInfo);
ctx.LoadAll();
InitGL(wnd, ctx);
Int32 width = 512;
Int32 height = 512;
uint fbo = CreateFBO();
uint texture = CreateTexture2D(width, height);
GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
{
GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, texture, 0);
GL.glPushAttrib(GL.GL_ALL_ATTRIB_BITS);
{
GL.glViewport(0, 0, width, height);
GL.glMatrixMode(GL.GL_PROJECTION);
GL.glLoadIdentity();
GL.glMatrixMode(GL.GL_MODELVIEW);
GL.glLoadIdentity();
GL.glOrtho(0, 1, 0, 1, -1, 1);
GL.glClearColor(0, 0, 0, 1.0f);
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
GL.glBegin(GL.GL_TRIANGLES);
{
for (int i = 0; i < 50; i++)
{
GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
}
}
GL.glEnd();
}
GL.glPopAttrib();
}
GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
InitViewport(wnd, ctx);
while (wnd.Exists)
{
GL.glClear(GL.GL_COLOR_BUFFER_BIT);
GL.glPushMatrix();
GL.glPushAttrib(GL.GL_TEXTURE_BIT | GL.GL_CURRENT_BIT);
{
GL.glTranslatef(-0.5f, -0.5f, 0);
GL.glPushMatrix();
GL.glPushAttrib(GL.GL_TEXTURE_BIT | GL.GL_CURRENT_BIT);
{
GL.glTranslatef(-0.5f, 0f, 0);
for (int strip = 0; strip < strips; strip++)
{
GL.glBegin(GL.GL_TRIANGLE_STRIP);
{
for (int stripComponent = 0; stripComponent < stripComponents; stripComponent++)
{
GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
}
}
GL.glEnd();
}
}
GL.glPopAttrib();
GL.glPopMatrix();
GL.glPushMatrix();
GL.glPushAttrib(GL.GL_TEXTURE_BIT | GL.GL_CURRENT_BIT);
{
GL.glTranslatef(0.5f, 0f, 0);
GL.glColor4f(1, 1, 1, 1);
GL.glBindTexture(GL.GL_TEXTURE_2D, texture);
GL.glBegin(GL.GL_QUADS);
{
GL.glTexCoord2f(0, 1); GL.glVertex2f(0, 1);
GL.glTexCoord2f(0, 0); GL.glVertex2f(0, 0);
GL.glTexCoord2f(1, 0); GL.glVertex2f(1, 0);
GL.glTexCoord2f(1, 1); GL.glVertex2f(1, 1);
}
GL.glEnd();
}
GL.glPopAttrib();
GL.glPopMatrix();
}
GL.glPopAttrib();
GL.glPopMatrix();
ctx.SwapBuffers();
wnd.ProcessEvents();
}
}
}
}