151 lines
4.1 KiB
C++
151 lines
4.1 KiB
C++
/*
|
|
Copyright 2021 flyinghead
|
|
|
|
This file is part of Flycast.
|
|
|
|
Flycast is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Flycast is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "quad.h"
|
|
|
|
static const char* VertexShader = R"(
|
|
in highp vec3 in_pos;
|
|
in mediump vec2 in_uv;
|
|
out mediump vec2 vtx_uv;
|
|
|
|
void main()
|
|
{
|
|
vtx_uv = in_uv;
|
|
#if ROTATE == 1
|
|
gl_Position = vec4(-in_pos.y, in_pos.x, in_pos.z, 1.0);
|
|
#else
|
|
gl_Position = vec4(in_pos, 1.0);
|
|
#endif
|
|
}
|
|
)";
|
|
|
|
static const char* FragmentShader = R"(
|
|
in mediump vec2 vtx_uv;
|
|
|
|
uniform sampler2D tex;
|
|
uniform mediump vec4 tint;
|
|
|
|
void main()
|
|
{
|
|
gl_FragColor = tint * texture(tex, vtx_uv);
|
|
}
|
|
)";
|
|
|
|
GlQuadDrawer::GlQuadDrawer()
|
|
{
|
|
OpenGlSource fragmentShader;
|
|
fragmentShader.addSource(PixelCompatShader)
|
|
.addSource(FragmentShader);
|
|
OpenGlSource vertexShader;
|
|
vertexShader.addConstant("ROTATE", 0)
|
|
.addSource(VertexCompatShader)
|
|
.addSource(VertexShader);
|
|
|
|
const std::string fragmentGlsl = fragmentShader.generate();
|
|
shader = gl_CompileAndLink(vertexShader.generate().c_str(), fragmentGlsl.c_str());
|
|
GLint tex = glGetUniformLocation(shader, "tex");
|
|
glUniform1i(tex, 0); // texture 0
|
|
tintUniform = glGetUniformLocation(shader, "tint");
|
|
|
|
vertexShader.setConstant("ROTATE", 1);
|
|
rot90shader = gl_CompileAndLink(vertexShader.generate().c_str(), fragmentGlsl.c_str());
|
|
tex = glGetUniformLocation(rot90shader, "tex");
|
|
glUniform1i(tex, 0); // texture 0
|
|
rot90TintUniform = glGetUniformLocation(rot90shader, "tint");
|
|
|
|
quadIndexBuffer = std::make_unique<GlBuffer>(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW);
|
|
static const GLushort indices[] = { 0, 1, 2, 1, 3 };
|
|
quadIndexBuffer->update(indices, sizeof(indices));
|
|
|
|
quadBuffer = std::make_unique<GlBuffer>(GL_ARRAY_BUFFER, GL_STATIC_DRAW);
|
|
{
|
|
float vertices[4][5] = {
|
|
{ -1.f, 1.f, 1.f, 0.f, 1.f },
|
|
{ -1.f, -1.f, 1.f, 0.f, 0.f },
|
|
{ 1.f, 1.f, 1.f, 1.f, 1.f },
|
|
{ 1.f, -1.f, 1.f, 1.f, 0.f },
|
|
};
|
|
quadBuffer->update(vertices, sizeof(vertices));
|
|
}
|
|
quadBufferSwapY = std::make_unique<GlBuffer>(GL_ARRAY_BUFFER, GL_STATIC_DRAW);
|
|
{
|
|
float vertices[4][5] = {
|
|
{ -1.f, 1.f, 1.f, 0.f, 0.f },
|
|
{ -1.f, -1.f, 1.f, 0.f, 1.f },
|
|
{ 1.f, 1.f, 1.f, 1.f, 0.f },
|
|
{ 1.f, -1.f, 1.f, 1.f, 1.f },
|
|
};
|
|
quadBufferSwapY->update(vertices, sizeof(vertices));
|
|
}
|
|
quadBufferCustom = std::make_unique<GlBuffer>(GL_ARRAY_BUFFER);
|
|
glCheck();
|
|
}
|
|
|
|
GlQuadDrawer::~GlQuadDrawer()
|
|
{
|
|
quadIndexBuffer.reset();
|
|
quadBuffer.reset();
|
|
quadBufferSwapY.reset();
|
|
quadBufferCustom.reset();
|
|
|
|
quadVertexArray.term();
|
|
quadVertexArraySwapY.term();
|
|
quadVertexArrayCustom.term();
|
|
|
|
glcache.DeleteProgram(shader);
|
|
shader = 0;
|
|
glcache.DeleteProgram(rot90shader);
|
|
rot90shader = 0;
|
|
}
|
|
|
|
void GlQuadDrawer::draw(GLuint texId, bool rotate, bool swapY, const float *coords, const float *color)
|
|
{
|
|
glcache.Disable(GL_SCISSOR_TEST);
|
|
glcache.Disable(GL_DEPTH_TEST);
|
|
glcache.Disable(GL_STENCIL_TEST);
|
|
glcache.Disable(GL_CULL_FACE);
|
|
|
|
glcache.UseProgram(rotate ? rot90shader : shader);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glcache.BindTexture(GL_TEXTURE_2D, texId);
|
|
|
|
if (color == nullptr) {
|
|
static constexpr float white[4] { 1.f, 1.f, 1.f, 1.f };
|
|
color = white;
|
|
}
|
|
glUniform4fv(rotate ? rot90TintUniform : tintUniform, 1, color);
|
|
|
|
if (coords == nullptr)
|
|
{
|
|
if (swapY)
|
|
quadVertexArraySwapY.bind(quadBufferSwapY.get(), quadIndexBuffer.get());
|
|
else
|
|
quadVertexArray.bind(quadBuffer.get(), quadIndexBuffer.get());
|
|
}
|
|
else
|
|
{
|
|
quadBufferCustom->update(coords, sizeof(float) * 4 * 5);
|
|
quadVertexArrayCustom.bind(quadBufferCustom.get(), quadIndexBuffer.get());
|
|
}
|
|
|
|
glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, (GLvoid *)0);
|
|
GlVertexArray::unbind();
|
|
glCheck();
|
|
}
|