mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-23 20:40:09 +00:00
video_core: Make the OpenGL renderer work on GL 2.0+ and GLES 2.0+
This commit is contained in:
parent
8885c118ff
commit
6e95f273cc
@ -10,7 +10,7 @@
|
||||
|
||||
namespace ShaderUtil {
|
||||
|
||||
GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
|
||||
GLuint LoadShaders(const char* glsl_header, const char* vertex_shader, const char* fragment_shader) {
|
||||
|
||||
// Create the shaders
|
||||
GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
|
||||
@ -22,7 +22,8 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
|
||||
// Compile Vertex Shader
|
||||
LOG_DEBUG(Render_OpenGL, "Compiling vertex shader...");
|
||||
|
||||
glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr);
|
||||
const char* vertex_source[2] = {glsl_header, vertex_shader};
|
||||
glShaderSource(vertex_shader_id, 2, vertex_source, nullptr);
|
||||
glCompileShader(vertex_shader_id);
|
||||
|
||||
// Check Vertex Shader
|
||||
@ -42,7 +43,8 @@ GLuint LoadShaders(const char* vertex_shader, const char* fragment_shader) {
|
||||
// Compile Fragment Shader
|
||||
LOG_DEBUG(Render_OpenGL, "Compiling fragment shader...");
|
||||
|
||||
glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr);
|
||||
const char* fragment_source[2] = {glsl_header, fragment_shader};
|
||||
glShaderSource(fragment_shader_id, 2, fragment_source, nullptr);
|
||||
glCompileShader(fragment_shader_id);
|
||||
|
||||
// Check Fragment Shader
|
||||
|
@ -8,6 +8,6 @@
|
||||
|
||||
namespace ShaderUtil {
|
||||
|
||||
GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path);
|
||||
GLuint LoadShaders(const char* glsl_header, const char* vertex_shader, const char* fragment_shader);
|
||||
|
||||
}
|
||||
|
@ -7,38 +7,40 @@
|
||||
namespace GLShaders {
|
||||
|
||||
const char g_vertex_shader[] = R"(
|
||||
#version 150 core
|
||||
#if GL_ES && __VERSION__ >= 300 || !GL_ES && __VERSION__ >= 130
|
||||
#define attribute in
|
||||
#define varying out
|
||||
#endif
|
||||
|
||||
in vec2 vert_position;
|
||||
in vec2 vert_tex_coord;
|
||||
out vec2 frag_tex_coord;
|
||||
attribute mediump vec2 vert_position;
|
||||
attribute mediump vec2 vert_tex_coord;
|
||||
varying mediump vec2 frag_tex_coord;
|
||||
|
||||
// This is a truncated 3x3 matrix for 2D transformations:
|
||||
// The upper-left 2x2 submatrix performs scaling/rotation/mirroring.
|
||||
// The third column performs translation.
|
||||
// The third row could be used for projection, which we don't need in 2D. It hence is assumed to
|
||||
// implicitly be [0, 0, 1]
|
||||
uniform mat3x2 modelview_matrix;
|
||||
uniform mat3 modelview_matrix;
|
||||
|
||||
void main() {
|
||||
// Multiply input position by the rotscale part of the matrix and then manually translate by
|
||||
// the last column. This is equivalent to using a full 3x3 matrix and expanding the vector
|
||||
// to `vec3(vert_position.xy, 1.0)`
|
||||
gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0);
|
||||
gl_Position = vec4(modelview_matrix * vec3(vert_position, 1.0), 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
)";
|
||||
|
||||
const char g_fragment_shader[] = R"(
|
||||
#version 150 core
|
||||
#if GL_ES && __VERSION__ >= 300 || !GL_ES && __VERSION__ >= 130
|
||||
#define varying in
|
||||
#endif
|
||||
|
||||
in vec2 frag_tex_coord;
|
||||
out vec4 color;
|
||||
varying mediump vec2 frag_tex_coord;
|
||||
|
||||
#if GL_ES && __VERSION__ >= 300
|
||||
out mediump vec4 color;
|
||||
#else
|
||||
#define color gl_FragColor
|
||||
#endif
|
||||
|
||||
uniform sampler2D color_texture;
|
||||
|
||||
void main() {
|
||||
color = texture(color_texture, frag_tex_coord);
|
||||
color = texture2D(color_texture, frag_tex_coord);
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -34,12 +34,12 @@ struct ScreenRectVertex {
|
||||
* The projection part of the matrix is trivial, hence these operations are represented
|
||||
* by a 3x2 matrix.
|
||||
*/
|
||||
static std::array<GLfloat, 3*2> MakeOrthographicMatrix(const float width, const float height) {
|
||||
std::array<GLfloat, 3*2> matrix;
|
||||
static std::array<GLfloat, 3*3> MakeOrthographicMatrix(const float width, const float height) {
|
||||
std::array<GLfloat, 3*3> matrix;
|
||||
|
||||
matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f;
|
||||
matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f;
|
||||
// Last matrix row is implicitly assumed to be [0, 0, 1].
|
||||
matrix[0] = 2.f / width; matrix[3] = 0.f; matrix[6] = -1.f;
|
||||
matrix[1] = 0.f; matrix[4] = -2.f / height; matrix[7] = 1.f;
|
||||
matrix[2] = 0.f; matrix[5] = 0.f; matrix[8] = 1.f;
|
||||
|
||||
return matrix;
|
||||
}
|
||||
@ -131,11 +131,38 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig&
|
||||
* Initializes the OpenGL state and creates persistent objects.
|
||||
*/
|
||||
void RendererOpenGL::InitOpenGLObjects() {
|
||||
std::string glsl_header;
|
||||
|
||||
// Select the right GLSL version for our context
|
||||
int version = epoxy_gl_version();
|
||||
if (epoxy_is_desktop_gl()) {
|
||||
if (version == 20)
|
||||
glsl_header = "#version 110\n";
|
||||
else if (version == 21)
|
||||
glsl_header = "#version 120\n";
|
||||
else if (version == 30)
|
||||
glsl_header = "#version 130\n";
|
||||
else if (version == 31)
|
||||
glsl_header = "#version 140\n";
|
||||
else if (version == 32)
|
||||
glsl_header = "#version 150\n";
|
||||
else
|
||||
glsl_header = "#version " + std::to_string(version * 10) + "\n";
|
||||
|
||||
// Desktop OpenGL doesn’t support precision qualifiers.
|
||||
glsl_header += "#define mediump\n";
|
||||
} else {
|
||||
if (version == 20)
|
||||
glsl_header = "#version 100\n";
|
||||
else
|
||||
glsl_header = "#version " + std::to_string(version * 10) + " es\n";
|
||||
}
|
||||
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
// Link shaders and get variable locations
|
||||
program_id = ShaderUtil::LoadShaders(GLShaders::g_vertex_shader, GLShaders::g_fragment_shader);
|
||||
program_id = ShaderUtil::LoadShaders(glsl_header.c_str(), GLShaders::g_vertex_shader, GLShaders::g_fragment_shader);
|
||||
uniform_modelview_matrix = glGetUniformLocation(program_id, "modelview_matrix");
|
||||
uniform_color_texture = glGetUniformLocation(program_id, "color_texture");
|
||||
attrib_position = glGetAttribLocation(program_id, "vert_position");
|
||||
@ -201,8 +228,8 @@ void RendererOpenGL::DrawScreens() {
|
||||
glUseProgram(program_id);
|
||||
|
||||
// Set projection matrix
|
||||
std::array<GLfloat, 3*2> ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height);
|
||||
glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
|
||||
std::array<GLfloat, 3*3> ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height);
|
||||
glUniformMatrix3fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
|
||||
|
||||
// Bind texture in Texture Unit 0
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
Loading…
Reference in New Issue
Block a user