00001
00002
00003 #ifndef NV_SIMPLE_FBO_H
00004 #define NV_SIMPLE_FBO_H
00005
00006 #include <NvFoundation.h>
00007
00008
00009 #include "NV/NvPlatformGL.h"
00010 #include "NV/NvLogs.h"
00011 #include <stdlib.h>
00012
00015
00019 class NvWritableFB
00020 {
00021 public:
00022
00027 NvWritableFB(GLuint w, GLuint h): fbo(0), width(w), height(h) {}
00028
00031 ~NvWritableFB()
00032 {
00033 if (fbo)
00034 {
00035 glDeleteFramebuffers(1, &fbo);
00036 fbo = 0;
00037 }
00038 }
00039
00040
00043 void bind()
00044 {
00045 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00046 glViewport(0, 0, width, height);
00047 }
00048
00049 GLuint fbo;
00050 GLuint width;
00051 GLuint height;
00052 };
00053
00057 class NvSimpleFBO : public NvWritableFB
00058 {
00059 public:
00062 struct TextureDesc
00063 {
00064 TextureDesc()
00065 : format(0)
00066 , type(0)
00067 , wrap(GL_CLAMP_TO_EDGE)
00068 , filter(GL_NEAREST)
00069 {
00070 }
00071 GLenum format;
00072 GLenum type;
00073 GLint wrap;
00074 GLint filter;
00075 };
00076
00079 struct Desc
00080 {
00081 Desc()
00082 : width(0)
00083 , height(0)
00084 {
00085 }
00086 GLuint width;
00087 GLuint height;
00088 TextureDesc color;
00089 TextureDesc depth;
00090 };
00091
00093 NvSimpleFBO(const NvSimpleFBO::Desc& desc)
00094 : NvWritableFB(desc.width, desc.height)
00095 , colorTexture(0)
00096 , depthTexture(0)
00097 {
00098 glGenFramebuffers(1, &fbo);
00099
00100 if (desc.color.format)
00101 {
00102 colorTexture = createColorTexture2D(desc);
00103 CHECK_GL_ERROR();
00104
00105 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00106 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
00107 }
00108
00109 if (desc.depth.format)
00110 {
00111 depthTexture = createDepthTexture2D(desc);
00112 CHECK_GL_ERROR();
00113
00114 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00115 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
00116 }
00117
00118 checkStatus();
00119
00120 width = desc.width;
00121 height = desc.height;
00122
00123 glBindFramebuffer(GL_FRAMEBUFFER, 0);
00124 }
00125
00126 ~NvSimpleFBO()
00127 {
00128 if (colorTexture)
00129 {
00130 glDeleteTextures(1, &colorTexture);
00131 colorTexture = 0;
00132 }
00133 if (depthTexture)
00134 {
00135 glDeleteTextures(1, &depthTexture);
00136 depthTexture = 0;
00137 }
00138 if (fbo)
00139 {
00140 glDeleteFramebuffers(1, &fbo);
00141 fbo = 0;
00142 }
00143 }
00144
00145 void checkStatus()
00146 {
00147 GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
00148 switch (status)
00149 {
00150 case GL_FRAMEBUFFER_COMPLETE:
00151 break;
00152 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
00153 LOGE("Can't create FBO: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT error");
00154 break;
00155 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
00156 LOGE("Can't create FBO: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT error");
00157 break;
00158 #if 0
00159 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
00160 LOGE("Can't create FBO: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS error");
00161 break;
00162 #endif
00163 case GL_FRAMEBUFFER_UNSUPPORTED:
00164 LOGE("Can't create FBO: GL_FRAMEBUFFER_UNSUPPORTED error");
00165 break;
00166 default:
00167 LOGE("Can't create FBO: unknown error");
00168 break;
00169 }
00170 }
00171
00172 GLuint colorTexture;
00173 GLuint depthTexture;
00174
00175 protected:
00176 GLuint createColorTexture2D(const NvSimpleFBO::Desc& desc)
00177 {
00178 GLuint texture;
00179 glGenTextures(1, &texture);
00180 glBindTexture(GL_TEXTURE_2D, texture);
00181 glTexImage2D(GL_TEXTURE_2D, 0, desc.color.format, desc.width, desc.height, 0, desc.color.format, desc.color.type, NULL);
00182 CHECK_GL_ERROR();
00183
00184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, desc.color.wrap);
00185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, desc.color.wrap);
00186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, desc.color.filter);
00187 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, desc.color.filter);
00188
00189 return texture;
00190 }
00191
00192 GLuint createDepthTexture2D(const NvSimpleFBO::Desc& desc)
00193 {
00194 GLuint texture;
00195 glGenTextures(1, &texture);
00196 glBindTexture(GL_TEXTURE_2D, texture);
00197 glTexImage2D(GL_TEXTURE_2D, 0, desc.depth.format, desc.width, desc.height, 0, desc.depth.format, desc.depth.type, NULL);
00198 CHECK_GL_ERROR();
00199
00200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, desc.depth.wrap);
00201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, desc.depth.wrap);
00202 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, desc.depth.filter);
00203 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, desc.depth.filter);
00204
00205 return texture;
00206 }
00207 };
00208
00209 #endif