#include <errno.h>
#include "../libsdl/print.h"
#include "opengl.h"
-#define GL3_PROTOTYPES 1
+#define GLEW_STATIC
#include <GL/glew.h>
#define MAX_OSD 2
static int texture_size;
static int osd_size[MAX_OSD];
static int flip_y;
+static GLuint shadow_framebuffer[2] = { 0, 0 };
+static int current_view_width = 0, current_view_height = 0;
+static GLuint shadow_texture[2];
+static int shadow_texture_width = 0, shadow_texture_height = 0;
+static int shadow_multisampling;
+
+GLuint current_framebuffer = 0;
+
/* alloc and init an image texture with size that is greater than the power of two */
int init_opengl_image(int _image_width, int _image_height)
glClear(GL_COLOR_BUFFER_BIT);
}
+/* only set view width and heigt. (used by ovr to tell frame buffer size) */
+void opengl_set_size(int view_width, int view_height)
+{
+ current_view_width = view_width;
+ current_view_height = view_height;
+}
+
/* set viewport for improved rendering */
void opengl_viewport(int view_width, int view_height, int split, int benson_at_line, double fov, double benson_size)
{
else if (view_height * image_width < view_width * image_height)
factor_width = (double)(view_width * image_height) / (double)(view_height * image_width);
+ current_view_width = view_width;
+ current_view_height = view_height;
+
/* avoid views that are too small */
if (view_width < 1 || view_height < 1)
return;
}
}
+/* set color and alpha */
+void opengl_render_color_alpha(double r, double g, double b, double a)
+{
+ glDisable(GL_BLEND);
+ glColor4d(r, g, b, a);
+}
+
/* render polygon */
void opengl_render_polygon(double *x, double *y, double *z, int count, int cull_face)
{
}
}
+int init_shadow_buffer(int multisampling)
+{
+ shadow_multisampling = multisampling;
+
+ glGenFramebuffers(2, shadow_framebuffer);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, current_framebuffer);
+
+ return 0;
+}
+
+/* change to shadow buffer and clear it */
+void begin_shadow_render(void)
+{
+ /* free texture, if size changes */
+ if (shadow_texture[0] && (current_view_width != shadow_texture_width || current_view_height != shadow_texture_height)) {
+ glDeleteTextures(2, shadow_texture);
+ shadow_texture[0] = 0;
+ }
+ /* generate texture for shadow rendering (two, if MSAA is used) */
+ if (!shadow_texture[0]) {
+ glGenTextures(2, shadow_texture);
+ shadow_texture_width = current_view_width;
+ shadow_texture_height = current_view_height;
+ if (shadow_multisampling > 1) {
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, shadow_texture[0]);
+ glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, shadow_multisampling, GL_RGBA, shadow_texture_width, shadow_texture_height, 0);
+ glBindTexture(GL_TEXTURE_2D, shadow_texture[1]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shadow_texture_width, shadow_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, shadow_texture[0]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shadow_texture_width, shadow_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ }
+ }
+
+ /* switch to shadow_framebuffer now and attach the first texture */
+ glBindFramebuffer(GL_FRAMEBUFFER, shadow_framebuffer[0]);
+ if (shadow_multisampling > 1)
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, shadow_texture[0], 0);
+ else
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shadow_texture[0], 0);
+ GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
+ glDrawBuffers(1, DrawBuffers);
+ if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+ fprintf(stderr, "failed to create shadow texture\n");
+ }
+
+ /* clear to black + transparent */
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+/* apply shadow from shadow_framebuffer to current_framebuffer and switch to it */
+void end_shadow_render(void)
+{
+ if (shadow_multisampling > 1) {
+ /* attach second texture to second frame buffer */
+ glBindFramebuffer(GL_FRAMEBUFFER, shadow_framebuffer[1]);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shadow_texture[1], 0);
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, shadow_texture[1]);
+ /* blit from first texture to second texture (MSAA to normal texture) */
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, shadow_framebuffer[0]);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shadow_framebuffer[1]);
+ glBlitFramebufferEXT( 0, 0, shadow_texture_width, shadow_texture_height, 0, 0, shadow_texture_width, shadow_texture_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
+
+ /* switch to color buffer */
+ glBindFramebuffer(GL_FRAMEBUFFER, current_framebuffer);
+
+ /* apply shadow by drawing texture to screen */
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4d(1, 1, 1, 1);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(-1, 1, -1, 1, -1, 1);
+
+ glEnable(GL_TEXTURE_2D);
+ if (shadow_multisampling > 1)
+ glBindTexture(GL_TEXTURE_2D, shadow_texture[1]);
+ else
+ glBindTexture(GL_TEXTURE_2D, shadow_texture[0]);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 1);
+ glVertex3f(-1, 1, 0);
+ glTexCoord2f(1, 1);
+ glVertex3f(1, 1, 0);
+ glTexCoord2f(1, 0);
+ glVertex3f(1, -1, 0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1, -1, 0);
+ glEnd();
+ glDisable(GL_TEXTURE_2D);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glDisable(GL_BLEND);
+}
+
/* free image texture */
void exit_opengl(void)
{
int i;
+ if (shadow_texture[0]) {
+ glDeleteTextures(2, shadow_texture);
+ shadow_texture[0] = 0;
+ }
+ if (shadow_framebuffer[0]) {
+ glDeleteFramebuffers(2, shadow_framebuffer);
+ shadow_framebuffer[0] = 0;
+ }
if (image_rgb) {
free(image_rgb);
image_rgb = NULL;