diff --git a/CMakeLists.txt b/CMakeLists.txt
index 277ed4f6..9c0ecbfa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,6 +35,7 @@ set(GLideN64_SOURCES
ZSort.cpp
Textures.cpp
TextDrawer.cpp
+ PostProcessor.cpp
VI.cpp
common/CommonAPIImpl_common.cpp
)
@@ -42,7 +43,7 @@ set(GLideN64_SOURCES
if(MUPENPLUSAPI)
add_definitions(
-DMUPENPLUSAPI
- -DTXFILTER_LIB
+ -DTXFILTER_LIB
)
include_directories( inc )
set(GLideN64_SOURCES_UNIX
@@ -98,14 +99,14 @@ if(UNIX)
)
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
if( NOT MUPENPLUSAPI)
- add_definitions(
+ add_definitions(
-D_DEBUG
- )
- find_package(PkgConfig)
- pkg_check_modules(GLIB REQUIRED glib-2.0)
- include_directories(${GLIB_INCLUDE_DIRS})
- find_package(GTK2 REQUIRED)
- include_directories(${GTK2_INCLUDE_DIRS})
+ )
+ find_package(PkgConfig)
+ pkg_check_modules(GLIB REQUIRED glib-2.0)
+ include_directories(${GLIB_INCLUDE_DIRS})
+ find_package(GTK2 REQUIRED)
+ include_directories(${GTK2_INCLUDE_DIRS})
endif( NOT MUPENPLUSAPI)
endif(UNIX)
@@ -166,43 +167,43 @@ if(NOT OPENGL_FOUND)
endif(NOT OPENGL_FOUND)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
- SET(GCC_CPP11_COMPILE_FLAGS "-std=c++0x -static-libgcc -static-libstdc++")
- SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_CPP11_COMPILE_FLAGS}" )
- SET(GCC_STATIC_LINK_FLAGS "-static-libgcc -static-libstdc++")
- SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_STATIC_LINK_FLAGS}" )
+ SET(GCC_CPP11_COMPILE_FLAGS "-std=c++0x -static-libgcc -static-libstdc++")
+ SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_CPP11_COMPILE_FLAGS}" )
+ SET(GCC_STATIC_LINK_FLAGS "-static-libgcc -static-libstdc++")
+ SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_STATIC_LINK_FLAGS}" )
endif()
add_library( ${GLideN64_DLL_NAME} SHARED ${GLideN64_SOURCES})
if( CMAKE_BUILD_TYPE STREQUAL "Debug")
SET_TARGET_PROPERTIES(
- ${GLideN64_DLL_NAME}
- PROPERTIES
- LINKER_LANGUAGE CXX # Or else we get an error message, because cmake can't figure out from the ".o"-suffix that it is a C-linker we need.
- PREFIX ""
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/plugin/debug
+ ${GLideN64_DLL_NAME}
+ PROPERTIES
+ LINKER_LANGUAGE CXX # Or else we get an error message, because cmake can't figure out from the ".o"-suffix that it is a C-linker we need.
+ PREFIX ""
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/plugin/debug
)
if(SDL)
- target_link_libraries(${GLideN64_DLL_NAME} PRIVATE ${OPENGL_LIBRARIES} ${SDL_LIBRARIES} ${FREETYPE_LIBRARIES} GLideNHQd )
+ target_link_libraries(${GLideN64_DLL_NAME} PRIVATE ${OPENGL_LIBRARIES} ${SDL_LIBRARIES} ${FREETYPE_LIBRARIES} GLideNHQd )
else(SDL)
- target_link_libraries(${GLideN64_DLL_NAME} PRIVATE ${OPENGL_LIBRARIES} ${FREETYPE_LIBRARIES} GLideNHQd )
+ target_link_libraries(${GLideN64_DLL_NAME} PRIVATE ${OPENGL_LIBRARIES} ${FREETYPE_LIBRARIES} GLideNHQd )
endif(SDL)
endif( CMAKE_BUILD_TYPE STREQUAL "Debug")
if( CMAKE_BUILD_TYPE STREQUAL "Release")
SET_TARGET_PROPERTIES(
- ${GLideN64_DLL_NAME}
- PROPERTIES
- LINKER_LANGUAGE CXX # Or else we get an error message, because cmake can't figure out from the ".o"-suffix that it is a C-linker we need.
- PREFIX ""
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/plugin/release
+ ${GLideN64_DLL_NAME}
+ PROPERTIES
+ LINKER_LANGUAGE CXX # Or else we get an error message, because cmake can't figure out from the ".o"-suffix that it is a C-linker we need.
+ PREFIX ""
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/plugin/release
)
if(SDL)
- target_link_libraries(${GLideN64_DLL_NAME} ${OPENGL_LIBRARIES} ${SDL_LIBRARIES} ${FREETYPE_LIBRARIES} GLideNHQ )
+ target_link_libraries(${GLideN64_DLL_NAME} ${OPENGL_LIBRARIES} ${SDL_LIBRARIES} ${FREETYPE_LIBRARIES} GLideNHQ )
else(SDL)
- target_link_libraries(${GLideN64_DLL_NAME} PRIVATE ${OPENGL_LIBRARIES} ${FREETYPE_LIBRARIES} GLideNHQ )
+ target_link_libraries(${GLideN64_DLL_NAME} PRIVATE ${OPENGL_LIBRARIES} ${FREETYPE_LIBRARIES} GLideNHQ )
endif(SDL)
endif( CMAKE_BUILD_TYPE STREQUAL "Release")
diff --git a/FrameBuffer.cpp b/FrameBuffer.cpp
index cb41bffc..71faa38c 100644
--- a/FrameBuffer.cpp
+++ b/FrameBuffer.cpp
@@ -14,6 +14,7 @@
#include "Types.h"
#include "Config.h"
#include "Debug.h"
+#include "PostProcessor.h"
using namespace std;
@@ -403,6 +404,9 @@ void FrameBufferList::renderBuffer(u32 _address)
srcY1 = srcY0 + VI.real_height;
}
+#if 1
+ PostProcessor::get().processTexture(pBuffer->m_pTexture);
+#endif
// glDisable(GL_SCISSOR_TEST) does not affect glBlitFramebuffer, at least on AMD
glScissor(0, 0, ogl.getScreenWidth(), ogl.getScreenHeight());
glDisable(GL_SCISSOR_TEST);
diff --git a/GLideN64.vcxproj b/GLideN64.vcxproj
index 8b76d60d..2831a075 100644
--- a/GLideN64.vcxproj
+++ b/GLideN64.vcxproj
@@ -293,6 +293,7 @@
+
@@ -372,6 +373,7 @@
+
diff --git a/GLideN64.vcxproj.filters b/GLideN64.vcxproj.filters
index 80a862e6..f0093bde 100644
--- a/GLideN64.vcxproj.filters
+++ b/GLideN64.vcxproj.filters
@@ -192,6 +192,9 @@
Source Files
+
+ Source Files
+
@@ -335,6 +338,9 @@
Header Files
+
+ Header Files
+
diff --git a/OpenGL.cpp b/OpenGL.cpp
index c177435b..033a7d92 100644
--- a/OpenGL.cpp
+++ b/OpenGL.cpp
@@ -27,6 +27,7 @@
#include "Config.h"
#include "Log.h"
#include "TextDrawer.h"
+#include "PostProcessor.h"
using namespace std;
@@ -1275,6 +1276,7 @@ void OGLRender::_initData()
Combiner_Init();
TextDrawer::get().init();
TFH.init();
+ PostProcessor::get().init();
m_renderState = rsNone;
gSP.changed = gDP.changed = 0xFFFFFFFF;
@@ -1293,6 +1295,7 @@ void OGLRender::_initData()
void OGLRender::_destroyData()
{
m_renderState = rsNone;
+ PostProcessor::get().destroy();
TextDrawer::get().destroy();
Combiner_Destroy();
FrameBuffer_Destroy();
diff --git a/OpenGL.h b/OpenGL.h
index 7e948dca..31d2c994 100644
--- a/OpenGL.h
+++ b/OpenGL.h
@@ -80,6 +80,8 @@ public:
};
RENDER_STATE getRenderState() const {return m_renderState;}
+ void dropRenderState() {m_renderState = rsNone;}
+
#ifdef __TRIBUFFER_OPT
u32 getIndexmap(u32 _v) const {return triangles.indexmap[_v];}
u32 getIndexmapNew(u32 _index, u32 _num);
diff --git a/PostProcessor.cpp b/PostProcessor.cpp
new file mode 100644
index 00000000..7bc75fe4
--- /dev/null
+++ b/PostProcessor.cpp
@@ -0,0 +1,197 @@
+#include
+
+#include "N64.h"
+#include "gSP.h"
+#include "PostProcessor.h"
+#include "GLSLCombiner.h"
+
+const char * vertexShader =
+"#version 330 core \n"
+"in highp vec2 aPosition; \n"
+"in highp vec2 aTexCoord; \n"
+"out mediump vec2 vTexCoord; \n"
+"void main(){ \n"
+"gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n"
+"vTexCoord = aTexCoord; \n"
+"} \n"
+;
+
+static const char* bloomShader =
+"#version 330 core \n"
+"in mediump vec2 vTexCoord; \n"
+"layout(binding = 0) uniform sampler2D bgl_RenderedTexture; \n"
+"out lowp vec4 fragColor; \n"
+"void main() \n"
+"{ \n"
+" vec4 sum = vec4(0); \n"
+" vec2 texcoord = vTexCoord; \n"
+" int j; \n"
+" int i; \n"
+" \n"
+" for( i= -4 ; i < 4; i++) \n"
+" { \n"
+" for (j = -3; j < 3; j++) \n"
+" { \n"
+" sum += texture2D(bgl_RenderedTexture, texcoord + vec2(j, i)*0.004) * 0.25; \n"
+" } \n"
+" } \n"
+" if (texture2D(bgl_RenderedTexture, texcoord).r < 0.3) \n"
+" { \n"
+" fragColor = sum*sum*0.012 + texture2D(bgl_RenderedTexture, texcoord); \n"
+" } \n"
+" else \n"
+" { \n"
+" if (texture2D(bgl_RenderedTexture, texcoord).r < 0.5) \n"
+" { \n"
+" fragColor = sum*sum*0.009 + texture2D(bgl_RenderedTexture, texcoord); \n"
+" } \n"
+" else \n"
+" { \n"
+" fragColor = sum*sum*0.0075 + texture2D(bgl_RenderedTexture, texcoord); \n"
+" } \n"
+" } \n"
+"} \n"
+;
+
+static const char* copyShader =
+"#version 330 core \n"
+"in mediump vec2 vTexCoord; \n"
+"layout(binding = 0) uniform sampler2D bgl_RenderedTexture; \n"
+"out lowp vec4 fragColor; \n"
+"void main() \n"
+"{ \n"
+" fragColor = texture2D(bgl_RenderedTexture, vTexCoord); \n"
+"} \n"
+;
+
+static
+GLuint _createShaderProgram(const char * _strVertex, const char * _strFragment)
+{
+ GLuint vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vertex_shader_object, 1, &_strVertex, NULL);
+ glCompileShader(vertex_shader_object);
+
+ GLuint fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fragment_shader_object, 1, &_strFragment, NULL);
+ glCompileShader(fragment_shader_object);
+
+ GLuint program = glCreateProgram();
+ glBindAttribLocation(program, SC_POSITION, "aPosition");
+ glBindAttribLocation(program, SC_TEXCOORD0, "aTexCoord");
+ glAttachShader(program, vertex_shader_object);
+ glAttachShader(program, fragment_shader_object);
+ glLinkProgram(program);
+ glDeleteShader(vertex_shader_object);
+ glDeleteShader(fragment_shader_object);
+ return program;
+}
+
+
+void PostProcessor::init()
+{
+ m_bloomProgram = _createShaderProgram(vertexShader, bloomShader);
+ m_copyProgram = _createShaderProgram(vertexShader, copyShader);
+
+ m_pTexture = textureCache().addFrameBufferTexture();
+ m_pTexture->format = G_IM_FMT_RGBA;
+ m_pTexture->clampS = 1;
+ m_pTexture->clampT = 1;
+ m_pTexture->frameBufferTexture = TRUE;
+ m_pTexture->maskS = 0;
+ m_pTexture->maskT = 0;
+ m_pTexture->mirrorS = 0;
+ m_pTexture->mirrorT = 0;
+ m_pTexture->realWidth = video().getWidth();
+ m_pTexture->realHeight = video().getHeight();
+ m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight * 4;
+ textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
+ glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_pTexture->realWidth, m_pTexture->realHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glGenFramebuffers(1, &m_FBO);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->glName, 0);
+ GLuint attachments[1] = { GL_COLOR_ATTACHMENT0 };
+ glDrawBuffers(1, attachments);
+ // check if everything is OK
+ assert(checkFBO());
+ assert(!isGLError());
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+
+}
+
+void PostProcessor::destroy()
+{
+ if (m_bloomProgram != 0)
+ glDeleteProgram(m_bloomProgram);
+
+ if (m_copyProgram != 0)
+ glDeleteProgram(m_copyProgram);
+
+ if (m_FBO != 0)
+ glDeleteFramebuffers(1, &m_FBO);
+
+ if (m_pTexture != NULL)
+ textureCache().removeFrameBufferTexture(m_pTexture);
+}
+
+PostProcessor & PostProcessor::get()
+{
+ static PostProcessor processor;
+ return processor;
+}
+
+void _setGLState() {
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+
+ static const float vert[] =
+ {
+ -1.0, -1.0, +0.0, +0.0,
+ +1.0, -1.0, +1.0, +0.0,
+ -1.0, +1.0, +0.0, +1.0,
+ +1.0, +1.0, +1.0, +1.0
+ };
+
+ glEnableVertexAttribArray(SC_POSITION);
+ glVertexAttribPointer(SC_POSITION, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (float*)vert);
+ glEnableVertexAttribArray(SC_TEXCOORD0);
+ glVertexAttribPointer(SC_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (float*)vert + 2);
+ glDisableVertexAttribArray(SC_COLOR);
+ glDisableVertexAttribArray(SC_TEXCOORD1);
+ glDisableVertexAttribArray(SC_NUMLIGHTS);
+ glViewport(0, 0, video().getWidth(), video().getHeight());
+}
+
+void PostProcessor::processTexture(CachedTexture * _pTexture)
+{
+ _setGLState();
+
+ textureCache().activateTexture(0, _pTexture);
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
+ glUseProgram(m_bloomProgram);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ textureCache().activateTexture(0, m_pTexture);
+ GLuint copyFBO = 0;
+ glGenFramebuffers(1, ©FBO);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFBO);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _pTexture->glName, 0);
+ assert(checkFBO());
+ glUseProgram(m_copyProgram);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glDeleteFramebuffers(1, ©FBO);
+ video().getRender().dropRenderState();
+ glUseProgram(0);
+ gSP.changed = CHANGED_VIEWPORT | CHANGED_TEXTURE;
+}
diff --git a/PostProcessor.h b/PostProcessor.h
new file mode 100644
index 00000000..6d6f017c
--- /dev/null
+++ b/PostProcessor.h
@@ -0,0 +1,28 @@
+#ifndef POST_PROCESSOR_H
+#define POST_PROCESSOR_H
+
+#include "Types.h"
+#include "OpenGL.h"
+#include "Textures.h"
+
+class PostProcessor {
+public:
+ void init();
+ void destroy();
+
+ void processTexture(CachedTexture * _pTexture);
+
+ static PostProcessor & get();
+
+private:
+ PostProcessor() : m_bloomProgram(0), m_copyProgram(0), m_FBO(0), m_pTexture(NULL) {};
+ PostProcessor(const PostProcessor & _other);
+
+ GLuint m_bloomProgram;
+ GLuint m_copyProgram;
+
+ GLuint m_FBO;
+ CachedTexture * m_pTexture;
+};
+
+#endif // POST_PROCESSOR_H