зеркало из https://github.com/AvaloniaUI/angle.git
227 строки
7.5 KiB
C++
227 строки
7.5 KiB
C++
//
|
|
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
|
|
// Based on Simple_Texture2D.c from
|
|
// Book: OpenGL(R) ES 2.0 Programming Guide
|
|
// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
|
|
// ISBN-10: 0321502795
|
|
// ISBN-13: 9780321502797
|
|
// Publisher: Addison-Wesley Professional
|
|
// URLs: http://safari.informit.com/9780321563835
|
|
// http://www.opengles-book.com
|
|
|
|
#include "SampleApplication.h"
|
|
#include "shader_utils.h"
|
|
#include "system_utils.h"
|
|
#include "texture_utils.h"
|
|
|
|
#include <cstring>
|
|
#include <iostream>
|
|
|
|
class MultipleDrawBuffersSample : public SampleApplication
|
|
{
|
|
public:
|
|
MultipleDrawBuffersSample()
|
|
: SampleApplication("MultipleDrawBuffers", 1280, 720)
|
|
{
|
|
}
|
|
|
|
virtual bool initialize()
|
|
{
|
|
// Check EXT_draw_buffers is supported
|
|
char *extensionString = (char*)glGetString(GL_EXTENSIONS);
|
|
if (strstr(extensionString, "GL_EXT_draw_buffers") != nullptr)
|
|
{
|
|
// Retrieve the address of glDrawBuffersEXT from EGL
|
|
mDrawBuffers = (PFNGLDRAWBUFFERSEXTPROC)eglGetProcAddress("glDrawBuffersEXT");
|
|
}
|
|
else
|
|
{
|
|
mDrawBuffers = glDrawBuffers;
|
|
}
|
|
|
|
if (!mDrawBuffers)
|
|
{
|
|
std::cerr << "Unable to load glDrawBuffers[EXT] entry point.";
|
|
return false;
|
|
}
|
|
|
|
std::stringstream vsStream;
|
|
vsStream << angle::GetExecutableDirectory() << "/multiple_draw_buffers_vs.glsl";
|
|
|
|
std::stringstream fsStream;
|
|
fsStream << angle::GetExecutableDirectory() << "/multiple_draw_buffers_fs.glsl";
|
|
|
|
std::stringstream copyFsStream;
|
|
fsStream << angle::GetExecutableDirectory() << "/multiple_draw_buffers_copy_fs.glsl";
|
|
|
|
mMRTProgram = CompileProgramFromFiles(vsStream.str(), fsStream.str());
|
|
if (!mMRTProgram)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
mCopyProgram = CompileProgramFromFiles(vsStream.str(), copyFsStream.str());
|
|
if (!mCopyProgram)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Get the attribute locations
|
|
mPositionLoc = glGetAttribLocation(mCopyProgram, "a_position");
|
|
mTexCoordLoc = glGetAttribLocation(mCopyProgram, "a_texCoord");
|
|
|
|
// Get the sampler location
|
|
mSamplerLoc = glGetUniformLocation(mCopyProgram, "s_texture");
|
|
|
|
// Load the texture
|
|
mTexture = CreateSimpleTexture2D();
|
|
|
|
// Initialize the user framebuffer
|
|
glGenFramebuffers(1, &mFramebuffer);
|
|
glGenTextures(mFramebufferAttachmentCount, mFramebufferTextures);
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
|
for (size_t i = 0; i < mFramebufferAttachmentCount; i++)
|
|
{
|
|
// Create textures for the four color attachments
|
|
glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[i]);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindow()->getWidth(),
|
|
getWindow()->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
static_cast<GLenum>(GL_COLOR_ATTACHMENT0_EXT + i), GL_TEXTURE_2D,
|
|
mFramebufferTextures[i], 0);
|
|
}
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual void destroy()
|
|
{
|
|
glDeleteProgram(mCopyProgram);
|
|
glDeleteProgram(mMRTProgram);
|
|
glDeleteTextures(1, &mTexture);
|
|
glDeleteTextures(mFramebufferAttachmentCount, mFramebufferTextures);
|
|
glDeleteFramebuffers(1, &mFramebuffer);
|
|
}
|
|
|
|
virtual void draw()
|
|
{
|
|
GLfloat vertices[] =
|
|
{
|
|
-0.8f, 0.8f, 0.0f, // Position 0
|
|
0.0f, 0.0f, // TexCoord 0
|
|
-0.8f, -0.8f, 0.0f, // Position 1
|
|
0.0f, 1.0f, // TexCoord 1
|
|
0.8f, -0.8f, 0.0f, // Position 2
|
|
1.0f, 1.0f, // TexCoord 2
|
|
0.8f, 0.8f, 0.0f, // Position 3
|
|
1.0f, 0.0f // TexCoord 3
|
|
};
|
|
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
|
|
GLenum drawBuffers[mFramebufferAttachmentCount] =
|
|
{
|
|
GL_COLOR_ATTACHMENT0_EXT,
|
|
GL_COLOR_ATTACHMENT1_EXT,
|
|
GL_COLOR_ATTACHMENT2_EXT,
|
|
GL_COLOR_ATTACHMENT3_EXT
|
|
};
|
|
|
|
// Enable drawing to the four color attachments of the user framebuffer
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
|
mDrawBuffers(mFramebufferAttachmentCount, drawBuffers);
|
|
|
|
// Set the viewport
|
|
GLint width = static_cast<GLint>(getWindow()->getWidth());
|
|
GLint height = static_cast<GLint>(getWindow()->getHeight());
|
|
glViewport(0, 0, width, height);
|
|
|
|
// Clear the color buffer
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
// Use the program object
|
|
glUseProgram(mMRTProgram);
|
|
|
|
// Load the vertex position
|
|
glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices);
|
|
glEnableVertexAttribArray(mPositionLoc);
|
|
|
|
// Load the texture coordinate
|
|
glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices + 3);
|
|
glEnableVertexAttribArray(mTexCoordLoc);
|
|
|
|
// Bind the texture
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, mTexture);
|
|
|
|
// Set the sampler texture unit to 0
|
|
glUniform1i(mSamplerLoc, 0);
|
|
|
|
// Draw the textured quad to the four render targets
|
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
|
|
|
// Enable the default framebuffer and single textured drawing
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
glUseProgram(mCopyProgram);
|
|
|
|
// Draw the four textured quads to a separate region in the viewport
|
|
glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[0]);
|
|
glViewport(0, 0, width / 2, height / 2);
|
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[1]);
|
|
glViewport(width / 2, 0, width / 2, height / 2);
|
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[2]);
|
|
glViewport(0, height / 2, width / 2, height / 2);
|
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[3]);
|
|
glViewport(width / 2, height / 2, width / 2, height / 2);
|
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
|
}
|
|
|
|
private:
|
|
// Handle to a program object
|
|
GLuint mMRTProgram;
|
|
GLuint mCopyProgram;
|
|
|
|
// Attribute locations
|
|
GLint mPositionLoc;
|
|
GLint mTexCoordLoc;
|
|
|
|
// Sampler location
|
|
GLint mSamplerLoc;
|
|
|
|
// Texture handle
|
|
GLuint mTexture;
|
|
|
|
// Framebuffer object handle
|
|
GLuint mFramebuffer;
|
|
|
|
// Framebuffer color attachments
|
|
static const size_t mFramebufferAttachmentCount = 4;
|
|
GLuint mFramebufferTextures[mFramebufferAttachmentCount];
|
|
|
|
// Loaded draw buffer entry points
|
|
PFNGLDRAWBUFFERSEXTPROC mDrawBuffers;
|
|
};
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
MultipleDrawBuffersSample app;
|
|
return app.run();
|
|
}
|