rev |
line source |
nuclear@2
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include "opengl.h"
|
nuclear@0
|
3 #include "rtarg.h"
|
nuclear@0
|
4
|
nuclear@0
|
5 static int next_pow2(int x);
|
nuclear@0
|
6
|
nuclear@0
|
7 RenderTarget::RenderTarget()
|
nuclear@0
|
8 {
|
nuclear@0
|
9 xsz = ysz = 0;
|
nuclear@0
|
10 fbo = color = depth = 0;
|
nuclear@0
|
11
|
nuclear@0
|
12 tex_fmt = 0;
|
nuclear@0
|
13 tex_xsz = tex_ysz = 0;
|
nuclear@0
|
14 }
|
nuclear@0
|
15
|
nuclear@0
|
16 RenderTarget::~RenderTarget()
|
nuclear@0
|
17 {
|
nuclear@0
|
18 destroy();
|
nuclear@0
|
19 }
|
nuclear@0
|
20
|
nuclear@0
|
21 bool RenderTarget::create(int xsz, int ysz)
|
nuclear@0
|
22 {
|
nuclear@0
|
23 destroy();
|
nuclear@0
|
24
|
nuclear@0
|
25 this->xsz = xsz;
|
nuclear@0
|
26 this->ysz = ysz;
|
nuclear@0
|
27
|
nuclear@0
|
28 tex_xsz = next_pow2(xsz);
|
nuclear@0
|
29 tex_ysz = next_pow2(ysz);
|
nuclear@2
|
30 tex_fmt = check_extension("GL_ARB_texture_float") ? GL_RGBA16F : GL_RGBA;
|
nuclear@0
|
31
|
nuclear@0
|
32 glGenFramebuffers(1, &fbo);
|
nuclear@0
|
33 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@0
|
34
|
nuclear@0
|
35 glGenTextures(1, &color);
|
nuclear@0
|
36 glBindTexture(GL_TEXTURE_2D, color);
|
nuclear@0
|
37 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@0
|
38 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@2
|
39 glTexImage2D(GL_TEXTURE_2D, 0, tex_fmt, tex_xsz, tex_ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
nuclear@0
|
40 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
|
nuclear@0
|
41
|
nuclear@0
|
42 glGenRenderbuffers(1, &depth);
|
nuclear@0
|
43 glBindRenderbuffer(GL_RENDERBUFFER, depth);
|
nuclear@0
|
44 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
|
nuclear@0
|
45 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
|
nuclear@0
|
46
|
nuclear@2
|
47 if(!is_complete()) {
|
nuclear@2
|
48 fprintf(stderr, "framebuffer incomplete\n");
|
nuclear@2
|
49 }
|
nuclear@2
|
50
|
nuclear@0
|
51 return true;
|
nuclear@0
|
52 }
|
nuclear@0
|
53
|
nuclear@0
|
54 bool RenderTarget::resize(int xsz, int ysz)
|
nuclear@0
|
55 {
|
nuclear@0
|
56 if(!fbo) {
|
nuclear@0
|
57 return create(xsz, ysz);
|
nuclear@0
|
58 }
|
nuclear@0
|
59
|
nuclear@0
|
60 this->xsz = xsz;
|
nuclear@0
|
61 this->ysz = ysz;
|
nuclear@0
|
62 int new_tex_xsz = next_pow2(xsz);
|
nuclear@0
|
63 int new_tex_ysz = next_pow2(ysz);
|
nuclear@0
|
64
|
nuclear@0
|
65 if(tex_xsz != new_tex_xsz || tex_ysz != new_tex_ysz) {
|
nuclear@0
|
66 glBindTexture(GL_TEXTURE_2D, color);
|
nuclear@0
|
67 glTexImage2D(GL_TEXTURE_2D, 0, tex_fmt, tex_xsz, tex_ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
nuclear@0
|
68
|
nuclear@0
|
69 glBindRenderbuffer(GL_RENDERBUFFER, depth);
|
nuclear@0
|
70 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz);
|
nuclear@0
|
71
|
nuclear@0
|
72 tex_xsz = new_tex_xsz;
|
nuclear@0
|
73 tex_ysz = new_tex_ysz;
|
nuclear@2
|
74
|
nuclear@2
|
75 if(!is_complete()) {
|
nuclear@2
|
76 fprintf(stderr, "framebuffer incomplete\n");
|
nuclear@2
|
77 }
|
nuclear@0
|
78 }
|
nuclear@0
|
79 return true;
|
nuclear@0
|
80 }
|
nuclear@0
|
81
|
nuclear@0
|
82 void RenderTarget::destroy()
|
nuclear@0
|
83 {
|
nuclear@0
|
84 if(fbo) {
|
nuclear@0
|
85 glDeleteFramebuffers(1, &fbo);
|
nuclear@0
|
86 }
|
nuclear@0
|
87 if(color) {
|
nuclear@0
|
88 glDeleteTextures(1, &color);
|
nuclear@0
|
89 }
|
nuclear@0
|
90 if(depth) {
|
nuclear@0
|
91 glDeleteRenderbuffers(1, &depth);
|
nuclear@0
|
92 }
|
nuclear@0
|
93 fbo = color = depth = 0;
|
nuclear@0
|
94 }
|
nuclear@0
|
95
|
nuclear@0
|
96 bool RenderTarget::is_valid() const
|
nuclear@0
|
97 {
|
nuclear@0
|
98 return fbo != 0;
|
nuclear@0
|
99 }
|
nuclear@0
|
100
|
nuclear@2
|
101 bool RenderTarget::is_complete() const
|
nuclear@2
|
102 {
|
nuclear@2
|
103 if(!fbo) return false;
|
nuclear@2
|
104
|
nuclear@2
|
105 unsigned int prev_fbo;
|
nuclear@2
|
106 glGetIntegerv(GL_FRAMEBUFFER_BINDING, (int*)&prev_fbo);
|
nuclear@2
|
107 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@2
|
108 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
nuclear@2
|
109 if(prev_fbo != fbo) {
|
nuclear@2
|
110 glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo);
|
nuclear@2
|
111 }
|
nuclear@2
|
112 return status == GL_FRAMEBUFFER_COMPLETE;
|
nuclear@2
|
113 }
|
nuclear@2
|
114
|
nuclear@0
|
115 unsigned int RenderTarget::get_texture() const
|
nuclear@0
|
116 {
|
nuclear@0
|
117 return color;
|
nuclear@0
|
118 }
|
nuclear@0
|
119
|
nuclear@0
|
120 int RenderTarget::get_width() const
|
nuclear@0
|
121 {
|
nuclear@0
|
122 return xsz;
|
nuclear@0
|
123 }
|
nuclear@0
|
124
|
nuclear@0
|
125 int RenderTarget::get_height() const
|
nuclear@0
|
126 {
|
nuclear@0
|
127 return ysz;
|
nuclear@0
|
128 }
|
nuclear@0
|
129
|
nuclear@0
|
130 int RenderTarget::get_tex_width() const
|
nuclear@0
|
131 {
|
nuclear@0
|
132 return tex_xsz;
|
nuclear@0
|
133 }
|
nuclear@0
|
134
|
nuclear@0
|
135 int RenderTarget::get_tex_height() const
|
nuclear@0
|
136 {
|
nuclear@0
|
137 return tex_ysz;
|
nuclear@0
|
138 }
|
nuclear@0
|
139
|
nuclear@0
|
140 void set_render_target(const RenderTarget *rtarg)
|
nuclear@0
|
141 {
|
nuclear@0
|
142 if(rtarg) {
|
nuclear@0
|
143 glBindFramebuffer(GL_FRAMEBUFFER, rtarg->color);
|
nuclear@0
|
144 } else {
|
nuclear@0
|
145 glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
nuclear@0
|
146 }
|
nuclear@0
|
147 }
|
nuclear@0
|
148
|
nuclear@0
|
149 static int next_pow2(int x)
|
nuclear@0
|
150 {
|
nuclear@0
|
151 x--;
|
nuclear@0
|
152 x = (x >> 1) | x;
|
nuclear@0
|
153 x = (x >> 2) | x;
|
nuclear@0
|
154 x = (x >> 4) | x;
|
nuclear@0
|
155 x = (x >> 8) | x;
|
nuclear@0
|
156 x = (x >> 16) | x;
|
nuclear@0
|
157 return x + 1;
|
nuclear@0
|
158 }
|