1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // Based on Simple_Texture2D.c from
8 // Book: OpenGL(R) ES 2.0 Programming Guide
9 // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
10 // ISBN-10: 0321502795
11 // ISBN-13: 9780321502797
12 // Publisher: Addison-Wesley Professional
13 // URLs: http://safari.informit.com/9780321563835
14 // http://www.opengles-book.com
15
16 #include "SampleApplication.h"
17
18 #include "texture_utils.h"
19 #include "util/shader_utils.h"
20 #include "util/test_utils.h"
21
22 #include <cstring>
23 #include <iostream>
24
25 class MultipleDrawBuffersSample : public SampleApplication
26 {
27 public:
MultipleDrawBuffersSample(int argc,char ** argv)28 MultipleDrawBuffersSample(int argc, char **argv)
29 : SampleApplication("MultipleDrawBuffers", argc, argv)
30 {}
31
initialize()32 bool initialize() override
33 {
34 // Check EXT_draw_buffers is supported
35 char *extensionString = (char *)glGetString(GL_EXTENSIONS);
36 if (strstr(extensionString, "GL_EXT_draw_buffers") != nullptr)
37 {
38 // Retrieve the address of glDrawBuffersEXT from EGL
39 mDrawBuffers = (PFNGLDRAWBUFFERSEXTPROC)eglGetProcAddress("glDrawBuffersEXT");
40 }
41 else
42 {
43 mDrawBuffers = glDrawBuffers;
44 }
45
46 if (!mDrawBuffers)
47 {
48 std::cerr << "Unable to load glDrawBuffers[EXT] entry point.";
49 return false;
50 }
51
52 std::stringstream vsStream;
53 vsStream << angle::GetExecutableDirectory() << "/multiple_draw_buffers_vs.glsl";
54
55 std::stringstream fsStream;
56 fsStream << angle::GetExecutableDirectory() << "/multiple_draw_buffers_fs.glsl";
57
58 std::stringstream copyFsStream;
59 copyFsStream << angle::GetExecutableDirectory() << "/multiple_draw_buffers_copy_fs.glsl";
60
61 mMRTProgram = CompileProgramFromFiles(vsStream.str(), fsStream.str());
62 if (!mMRTProgram)
63 {
64 return false;
65 }
66
67 mCopyProgram = CompileProgramFromFiles(vsStream.str(), copyFsStream.str());
68 if (!mCopyProgram)
69 {
70 return false;
71 }
72
73 // Get the attribute locations
74 mPositionLoc = glGetAttribLocation(mCopyProgram, "a_position");
75 mTexCoordLoc = glGetAttribLocation(mCopyProgram, "a_texCoord");
76
77 // Get the sampler location
78 mSamplerLoc = glGetUniformLocation(mCopyProgram, "s_texture");
79
80 // Load the texture
81 mTexture = CreateSimpleTexture2D();
82
83 // Initialize the user framebuffer
84 glGenFramebuffers(1, &mFramebuffer);
85 glGenTextures(mFramebufferAttachmentCount, mFramebufferTextures);
86
87 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
88 for (size_t i = 0; i < mFramebufferAttachmentCount; i++)
89 {
90 // Create textures for the four color attachments
91 glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[i]);
92 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindow()->getWidth(),
93 getWindow()->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
94 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
95 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
96 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
97 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
98 glFramebufferTexture2D(GL_FRAMEBUFFER,
99 static_cast<GLenum>(GL_COLOR_ATTACHMENT0_EXT + i), GL_TEXTURE_2D,
100 mFramebufferTextures[i], 0);
101 }
102
103 glBindTexture(GL_TEXTURE_2D, 0);
104
105 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
106
107 return true;
108 }
109
destroy()110 void destroy() override
111 {
112 glDeleteProgram(mCopyProgram);
113 glDeleteProgram(mMRTProgram);
114 glDeleteTextures(1, &mTexture);
115 glDeleteTextures(mFramebufferAttachmentCount, mFramebufferTextures);
116 glDeleteFramebuffers(1, &mFramebuffer);
117 }
118
draw()119 void draw() override
120 {
121 GLfloat vertices[] = {
122 -0.8f, 0.8f, 0.0f, // Position 0
123 0.0f, 0.0f, // TexCoord 0
124 -0.8f, -0.8f, 0.0f, // Position 1
125 0.0f, 1.0f, // TexCoord 1
126 0.8f, -0.8f, 0.0f, // Position 2
127 1.0f, 1.0f, // TexCoord 2
128 0.8f, 0.8f, 0.0f, // Position 3
129 1.0f, 0.0f // TexCoord 3
130 };
131 GLushort indices[] = {0, 1, 2, 0, 2, 3};
132 GLenum drawBuffers[mFramebufferAttachmentCount] = {
133 GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT,
134 GL_COLOR_ATTACHMENT3_EXT};
135
136 // Enable drawing to the four color attachments of the user framebuffer
137 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
138 mDrawBuffers(mFramebufferAttachmentCount, drawBuffers);
139
140 // Set the viewport
141 GLint width = static_cast<GLint>(getWindow()->getWidth());
142 GLint height = static_cast<GLint>(getWindow()->getHeight());
143 glViewport(0, 0, width, height);
144
145 // Clear the color buffer
146 glClear(GL_COLOR_BUFFER_BIT);
147
148 // Use the program object
149 glUseProgram(mMRTProgram);
150
151 // Load the vertex position
152 glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertices);
153 glEnableVertexAttribArray(mPositionLoc);
154
155 // Load the texture coordinate
156 glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat),
157 vertices + 3);
158 glEnableVertexAttribArray(mTexCoordLoc);
159
160 // Bind the texture
161 glActiveTexture(GL_TEXTURE0);
162 glBindTexture(GL_TEXTURE_2D, mTexture);
163
164 // Set the sampler texture unit to 0
165 glUniform1i(mSamplerLoc, 0);
166
167 // Draw the textured quad to the four render targets
168 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
169
170 // Enable the default framebuffer and single textured drawing
171 glBindFramebuffer(GL_FRAMEBUFFER, 0);
172 glUseProgram(mCopyProgram);
173
174 // Draw the four textured quads to a separate region in the viewport
175 glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[0]);
176 glViewport(0, 0, width / 2, height / 2);
177 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
178
179 glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[1]);
180 glViewport(width / 2, 0, width / 2, height / 2);
181 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
182
183 glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[2]);
184 glViewport(0, height / 2, width / 2, height / 2);
185 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
186
187 glBindTexture(GL_TEXTURE_2D, mFramebufferTextures[3]);
188 glViewport(width / 2, height / 2, width / 2, height / 2);
189 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
190 }
191
192 private:
193 // Handle to a program object
194 GLuint mMRTProgram;
195 GLuint mCopyProgram;
196
197 // Attribute locations
198 GLint mPositionLoc;
199 GLint mTexCoordLoc;
200
201 // Sampler location
202 GLint mSamplerLoc;
203
204 // Texture handle
205 GLuint mTexture;
206
207 // Framebuffer object handle
208 GLuint mFramebuffer;
209
210 // Framebuffer color attachments
211 static const size_t mFramebufferAttachmentCount = 4;
212 GLuint mFramebufferTextures[mFramebufferAttachmentCount];
213
214 // Loaded draw buffer entry points
215 PFNGLDRAWBUFFERSEXTPROC mDrawBuffers;
216 };
217
main(int argc,char ** argv)218 int main(int argc, char **argv)
219 {
220 MultipleDrawBuffersSample app(argc, argv);
221 return app.run();
222 }
223