diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index d857f7e82..1e80b07c6 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -618,17 +618,17 @@ void Canvas::drawv(const Matrix &t, const Vertex *v) predraw(); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableVertexAttribArray(ATTRIB_POS); + glEnableVertexAttribArray(ATTRIB_TEXCOORD); - glVertexPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].x); - glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].s); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &v[0].x); + glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &v[0].s); gl.prepareDraw(); gl.drawArrays(GL_QUADS, 0, 4); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); + glDisableVertexAttribArray(ATTRIB_TEXCOORD); + glDisableVertexAttribArray(ATTRIB_POS); postdraw(); } diff --git a/src/modules/graphics/opengl/Font.cpp b/src/modules/graphics/opengl/Font.cpp index 159d523b1..6d0865b42 100644 --- a/src/modules/graphics/opengl/Font.cpp +++ b/src/modules/graphics/opengl/Font.cpp @@ -383,11 +383,11 @@ void Font::print(const std::string &text, float x, float y, float extra_spacing, OpenGL::TempTransform transform(gl); transform.get() *= t; - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableVertexAttribArray(ATTRIB_POS); + glEnableVertexAttribArray(ATTRIB_TEXCOORD); - glVertexPointer(2, GL_FLOAT, sizeof(GlyphVertex), (GLvoid *)&glyphverts[0].x); - glTexCoordPointer(2, GL_FLOAT, sizeof(GlyphVertex), (GLvoid *)&glyphverts[0].s); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &glyphverts[0].x); + glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &glyphverts[0].s); gl.prepareDraw(); @@ -400,8 +400,8 @@ void Font::print(const std::string &text, float x, float y, float extra_spacing, gl.drawArrays(GL_QUADS, it->startvertex, it->vertexcount); } - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); + glDisableVertexAttribArray(ATTRIB_TEXCOORD); + glDisableVertexAttribArray(ATTRIB_POS); } int Font::getWidth(const std::string &str) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 6d023b443..7437853a2 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -69,6 +69,12 @@ Graphics::~Graphics() // We do this manually so the love objects get released before the window. states.clear(); + if (Shader::defaultShader) + { + Shader::defaultShader->release(); + Shader::defaultShader = nullptr; + } + currentWindow->release(); } @@ -280,6 +286,13 @@ bool Graphics::setMode(int width, int height, bool &sRGB) pixel_size_stack.reserve(5); pixel_size_stack.push_back(1); + // We always need a default shader. + if (!Shader::defaultShader) + Shader::defaultShader = newShader(Shader::defaultCode[0]); + + if (!getShader()) + setShader(Shader::defaultShader); + return true; } @@ -1080,10 +1093,10 @@ void Graphics::arc(DrawMode mode, float x, float y, float radius, float angle1, { gl.prepareDraw(); gl.bindTexture(0); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *) coords); + glEnableVertexAttribArray(ATTRIB_POS); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, coords); gl.drawArrays(GL_TRIANGLE_FAN, 0, points + 2); - glDisableClientState(GL_VERTEX_ARRAY); + glDisableVertexAttribArray(ATTRIB_POS); } delete[] coords; @@ -1104,10 +1117,10 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count) { gl.prepareDraw(); gl.bindTexture(0); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)coords); + glEnableVertexAttribArray(ATTRIB_POS); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, coords); gl.drawArrays(GL_POLYGON, 0, count/2-1); // opengl will close the polygon for us - glDisableClientState(GL_VERTEX_ARRAY); + glDisableVertexAttribArray(ATTRIB_POS); } } diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index f691f990b..2adedc9cd 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -410,17 +410,17 @@ void Image::drawv(const Matrix &t, const Vertex *v) predraw(); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableVertexAttribArray(ATTRIB_POS); + glEnableVertexAttribArray(ATTRIB_TEXCOORD); - glVertexPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].x); - glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].s); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &v[0].x); + glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &v[0].s); gl.prepareDraw(); gl.drawArrays(GL_QUADS, 0, 4); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); + glDisableVertexAttribArray(ATTRIB_TEXCOORD); + glDisableVertexAttribArray(ATTRIB_POS); postdraw(); } diff --git a/src/modules/graphics/opengl/Mesh.cpp b/src/modules/graphics/opengl/Mesh.cpp index 7bdbd1884..b62fd6c23 100644 --- a/src/modules/graphics/opengl/Mesh.cpp +++ b/src/modules/graphics/opengl/Mesh.cpp @@ -339,17 +339,17 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo // Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.) vbo->unmap(); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableVertexAttribArray(ATTRIB_POS); + glEnableVertexAttribArray(ATTRIB_TEXCOORD); - glVertexPointer(2, GL_FLOAT, sizeof(Vertex), vbo->getPointer(pos_offset)); - glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), vbo->getPointer(tex_offset)); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), vbo->getPointer(pos_offset)); + glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), vbo->getPointer(tex_offset)); if (hasVertexColors()) { // Per-vertex colors. - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), vbo->getPointer(color_offset)); + glEnableVertexAttribArray(ATTRIB_COLOR); + glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), vbo->getPointer(color_offset)); } GLenum mode = getGLDrawMode(draw_mode); @@ -391,12 +391,12 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo gl.drawArrays(mode, min, max - min + 1); } - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableVertexAttribArray(ATTRIB_TEXCOORD); + glDisableVertexAttribArray(ATTRIB_POS); if (hasVertexColors()) { - glDisableClientState(GL_COLOR_ARRAY); + glDisableVertexAttribArray(ATTRIB_COLOR); // Using the color array leaves the GL constant color undefined. gl.setColor(gl.getColor()); } diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index a696bb475..c94d46b89 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -75,15 +75,11 @@ void OpenGL::setupContext() if (!contextInitialized) return; - // Store the current color so we don't have to get it through GL later. - GLfloat glcolor[4]; - glGetFloatv(GL_CURRENT_COLOR, glcolor); - state.color.r = glcolor[0] * 255; - state.color.g = glcolor[1] * 255; - state.color.b = glcolor[2] * 255; - state.color.a = glcolor[3] * 255; + state.color = Color(255, 255, 255, 255); + GLfloat glcolor[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + glVertexAttrib4fv(ATTRIB_COLOR, glcolor); - // Same with the current clear color. + // Get the current clear color so we don't have to get it through GL later. glGetFloatv(GL_COLOR_CLEAR_VALUE, glcolor); state.clearColor.r = glcolor[0] * 255; state.clearColor.g = glcolor[1] * 255; @@ -360,7 +356,9 @@ void OpenGL::drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, cons void OpenGL::setColor(const Color &c) { - glColor4ubv(&c.r); + GLfloat glc[] = {c.r / 255.0f, c.g / 255.0f, c.b / 255.0f, c.a / 255.0f}; + glVertexAttrib4fv(ATTRIB_COLOR, glc); + state.color = c; } diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 63e263d19..cd22dc52f 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -48,6 +48,17 @@ namespace opengl // no clashes with other GL libraries when linking, etc. using namespace glad; +// Vertex attribute indices used in shaders by LOVE. The values map to OpenGL +// generic vertex attribute indices. +enum VertexAttribID +{ + ATTRIB_POS = 0, + ATTRIB_TEXCOORD, + ATTRIB_COLOR, + ATTRIB_PSEUDO_INSTANCE_ID, // Instance ID used with pseudo-instancing. + ATTRIB_MAX_ENUM +}; + /** * Thin layer between OpenGL and the rest of the program. * Internally shadows some OpenGL context state for improved efficiency and @@ -71,17 +82,6 @@ public: VENDOR_UNKNOWN }; - // Vertex attributes used in shaders by LOVE. The values map to OpenGL - // generic vertex attribute indices, when applicable. - // LOVE uses the old hard-coded attribute APIs for positions, colors, etc. - // (for now.) - enum VertexAttrib - { - // Instance ID when pseudo-instancing is used. - ATTRIB_PSEUDO_INSTANCE_ID = 1, - ATTRIB_MAX_ENUM - }; - // A rectangle representing an OpenGL viewport or a scissor box. struct Viewport { diff --git a/src/modules/graphics/opengl/ParticleSystem.cpp b/src/modules/graphics/opengl/ParticleSystem.cpp index c4c5b0524..e64fbb1dd 100644 --- a/src/modules/graphics/opengl/ParticleSystem.cpp +++ b/src/modules/graphics/opengl/ParticleSystem.cpp @@ -869,20 +869,20 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo texture->predraw(); - glEnableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableVertexAttribArray(ATTRIB_COLOR); + glEnableVertexAttribArray(ATTRIB_POS); + glEnableVertexAttribArray(ATTRIB_TEXCOORD); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), (GLvoid *) &particleVerts[0].r); - glVertexPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *) &particleVerts[0].x); - glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *) &particleVerts[0].s); + glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &particleVerts[0].r); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &particleVerts[0].x); + glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &particleVerts[0].s); gl.prepareDraw(); gl.drawArrays(GL_QUADS, 0, pCount * 4); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); + glDisableVertexAttribArray(ATTRIB_TEXCOORD); + glDisableVertexAttribArray(ATTRIB_POS); + glDisableVertexAttribArray(ATTRIB_COLOR); texture->postdraw(); diff --git a/src/modules/graphics/opengl/Polyline.cpp b/src/modules/graphics/opengl/Polyline.cpp index 58c2eff11..94f489f64 100644 --- a/src/modules/graphics/opengl/Polyline.cpp +++ b/src/modules/graphics/opengl/Polyline.cpp @@ -331,8 +331,8 @@ void Polyline::draw() // draw the core line gl.bindTexture(0); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)vertices); + glEnableVertexAttribArray(ATTRIB_POS); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, vertices); gl.drawArrays(draw_mode, 0, vertex_count); if (overdraw) @@ -342,18 +342,18 @@ void Polyline::draw() Color *colors = new Color[overdraw_vertex_count]; fill_color_array(colors, c); - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors); - glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)overdraw); + glEnableVertexAttribArray(ATTRIB_COLOR); + glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, overdraw); gl.drawArrays(draw_mode, 0, overdraw_vertex_count); - glDisableClientState(GL_COLOR_ARRAY); + glDisableVertexAttribArray(ATTRIB_COLOR); delete[] colors; gl.setColor(c); } - glDisableClientState(GL_VERTEX_ARRAY); + glDisableVertexAttribArray(ATTRIB_POS); } void Polyline::fill_color_array(Color *colors, const Color &c) diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index e548fa07e..30a32683b 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -62,6 +62,9 @@ namespace Shader *Shader::current = nullptr; +Shader *Shader::defaultShader = nullptr; + +Shader::ShaderSources Shader::defaultCode[1]; // TODO: RENDERER_MAX_ENUM GLint Shader::maxTexUnits = 0; std::vector Shader::textureCounters; @@ -178,18 +181,26 @@ void Shader::createProgram(const std::vector &shaderids) if (program == 0) throw love::Exception("Cannot create shader program object."); - for (GLuint id : shaderids) - glAttachShader(program, id); - - // Bind generic vertex attribute indices to names in the shader. - for (int i = 0; i < int(OpenGL::ATTRIB_MAX_ENUM); i++) + try { - OpenGL::VertexAttrib attrib = (OpenGL::VertexAttrib) i; + for (GLuint id : shaderids) + glAttachShader(program, id); + } + catch (love::Exception &) + { + glDeleteProgram(program); + throw; + } + + // Bind love's vertex attribute indices to names in the shader. + for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++) + { + VertexAttribID attrib = (VertexAttribID) i; // FIXME: We skip this both because pseudo-instancing is temporarily // disabled (see graphics.lua), and because binding a non-existant - // attribute name to a location causes a shader linker warning. - if (attrib == OpenGL::ATTRIB_PSEUDO_INSTANCE_ID) + // attribute name to a location can cause a shader linker warning. + if (attrib == ATTRIB_PSEUDO_INSTANCE_ID) continue; const char *name = nullptr; @@ -199,10 +210,6 @@ void Shader::createProgram(const std::vector &shaderids) glLinkProgram(program); - // flag shaders for auto-deletion when the program object is deleted. - for (GLuint id : shaderids) - glDeleteShader(id); - GLint status; glGetProgramiv(program, GL_LINK_STATUS, &status); @@ -211,9 +218,12 @@ void Shader::createProgram(const std::vector &shaderids) std::string warnings = getProgramWarnings(); glDeleteProgram(program); program = 0; - throw love::Exception("Cannot link shader program object:\n%s", warnings.c_str()); } + + // flag shaders for auto-deletion when the program object is deleted. + for (GLuint id : shaderids) + glDeleteShader(id); } void Shader::mapActiveUniforms() @@ -280,18 +290,38 @@ bool Shader::loadVolatile() shaderids.push_back(shaderid); } + // The shader program must have both vertex and pixel shader stages. + ShaderSources &defaults = defaultCode[0]; + + ShaderSources::const_iterator source = shaderSources.find(TYPE_VERTEX); + if (source == shaderSources.end()) + shaderids.push_back(compileCode(TYPE_VERTEX, defaults[TYPE_VERTEX])); + + source = shaderSources.find(TYPE_PIXEL); + if (source == shaderSources.end()) + shaderids.push_back(compileCode(TYPE_PIXEL, defaults[TYPE_PIXEL])); + if (shaderids.empty()) throw love::Exception("Cannot create shader: no valid source code!"); - createProgram(shaderids); + try + { + createProgram(shaderids); + } + catch (love::Exception &) + { + for (GLuint id : shaderids) + glDeleteShader(id); + throw; + } // Retreive all active uniform variables in this shader from OpenGL. mapActiveUniforms(); - for (int i = 0; i < int(OpenGL::ATTRIB_MAX_ENUM); i++) + for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++) { const char *name = nullptr; - if (attribNames.find(OpenGL::VertexAttrib(i), name)) + if (attribNames.find(VertexAttribID(i), name)) vertexAttributes[i] = glGetAttribLocation(program, name); else vertexAttributes[i] = -1; @@ -327,7 +357,7 @@ void Shader::unloadVolatile() // active texture list is probably invalid, clear it activeTexUnits.clear(); - activeTexUnits.insert(activeTexUnits.begin(), maxTexUnits, 0); + activeTexUnits.resize(maxTexUnits, 0); // same with uniform location list uniforms.clear(); @@ -416,72 +446,6 @@ const Shader::Uniform &Shader::getUniform(const std::string &name) const return it->second; } -int Shader::getUniformTypeSize(GLenum type) const -{ - switch (type) - { - case GL_INT: - case GL_FLOAT: - case GL_BOOL: - case GL_SAMPLER_1D: - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - return 1; - case GL_INT_VEC2: - case GL_FLOAT_VEC2: - case GL_FLOAT_MAT2: - case GL_BOOL_VEC2: - return 2; - case GL_INT_VEC3: - case GL_FLOAT_VEC3: - case GL_FLOAT_MAT3: - case GL_BOOL_VEC3: - return 3; - case GL_INT_VEC4: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT4: - case GL_BOOL_VEC4: - return 4; - default: - break; - } - - return 1; -} - -Shader::UniformType Shader::getUniformBaseType(GLenum type) const -{ - switch (type) - { - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - return UNIFORM_INT; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - return UNIFORM_FLOAT; - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - return UNIFORM_BOOL; - case GL_SAMPLER_1D: - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - return UNIFORM_SAMPLER; - default: - break; - } - - return UNIFORM_UNKNOWN; -} - void Shader::checkSetUniformError(const Uniform &u, int size, int count, UniformType sendtype) const { if (!program) @@ -611,11 +575,12 @@ void Shader::sendTexture(const std::string &name, Texture *texture) void Shader::retainObject(const std::string &name, Object *object) { + object->retain(); + auto it = boundRetainables.find(name); if (it != boundRetainables.end()) it->second->release(); - object->retain(); boundRetainables[name] = object; } @@ -669,7 +634,7 @@ Shader::UniformType Shader::getExternVariable(const std::string &name, int &comp return it->second.baseType; } -bool Shader::hasVertexAttrib(OpenGL::VertexAttrib attrib) const +bool Shader::hasVertexAttrib(VertexAttribID attrib) const { return vertexAttributes[int(attrib)] != -1; } @@ -771,6 +736,68 @@ bool Shader::isSupported() return getGLSLVersion() >= "1.2"; } +int Shader::getUniformTypeSize(GLenum type) const +{ + switch (type) + { + case GL_INT: + case GL_FLOAT: + case GL_BOOL: + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + return 1; + case GL_INT_VEC2: + case GL_FLOAT_VEC2: + case GL_FLOAT_MAT2: + case GL_BOOL_VEC2: + return 2; + case GL_INT_VEC3: + case GL_FLOAT_VEC3: + case GL_FLOAT_MAT3: + case GL_BOOL_VEC3: + return 3; + case GL_INT_VEC4: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT4: + case GL_BOOL_VEC4: + return 4; + default: + return 1; + } +} + +Shader::UniformType Shader::getUniformBaseType(GLenum type) const +{ + switch (type) + { + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + return UNIFORM_INT; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + return UNIFORM_FLOAT; + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + return UNIFORM_BOOL; + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + return UNIFORM_SAMPLER; + default: + return UNIFORM_UNKNOWN; + } +} + bool Shader::getConstant(const char *in, UniformType &out) { return uniformTypes.find(in, out); @@ -800,12 +827,15 @@ StringMap::Entry Shader::uniformT StringMap Shader::uniformTypes(Shader::uniformTypeEntries, sizeof(Shader::uniformTypeEntries)); -StringMap::Entry Shader::attribNameEntries[] = +StringMap::Entry Shader::attribNameEntries[] = { - {"love_PseudoInstanceID", OpenGL::ATTRIB_PSEUDO_INSTANCE_ID}, + {"VertexPosition", ATTRIB_POS}, + {"VertexTexCoord", ATTRIB_TEXCOORD}, + {"VertexColor", ATTRIB_COLOR}, + {"love_PseudoInstanceID", ATTRIB_PSEUDO_INSTANCE_ID}, }; -StringMap Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries)); +StringMap Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries)); StringMap::Entry Shader::builtinNameEntries[] = { diff --git a/src/modules/graphics/opengl/Shader.h b/src/modules/graphics/opengl/Shader.h index 38c70a137..019fd91ca 100644 --- a/src/modules/graphics/opengl/Shader.h +++ b/src/modules/graphics/opengl/Shader.h @@ -46,9 +46,6 @@ class Shader : public Object, public Volatile { public: - // Pointer to currently active Shader. - static Shader *current; - enum ShaderType { TYPE_VERTEX, @@ -77,6 +74,15 @@ public: // Type for a list of shader source codes in the form of sources[shadertype] = code typedef std::map ShaderSources; + // Pointer to currently active Shader. + static Shader *current; + + // Pointer to the default Shader. + static Shader *defaultShader; + + // Default shader code (a shader is always required internally.) + static ShaderSources defaultCode[1]; // TODO: RENDERER_MAX_ENUM + /** * Creates a new Shader using a list of source codes. * Sources must contain either vertex or pixel shader code, or both. @@ -162,7 +168,7 @@ public: /** * Internal use only. **/ - bool hasVertexAttrib(OpenGL::VertexAttrib attrib) const; + bool hasVertexAttrib(VertexAttribID attrib) const; bool hasBuiltinUniform(BuiltinUniform builtin) const; bool sendBuiltinFloat(BuiltinUniform builtin, int size, const GLfloat *m, int count); void checkSetScreenParams(); @@ -219,7 +225,7 @@ private: GLint builtinUniforms[BUILTIN_MAX_ENUM]; // Location values for any generic vertex attribute variables. - GLint vertexAttributes[OpenGL::ATTRIB_MAX_ENUM]; + GLint vertexAttributes[ATTRIB_MAX_ENUM]; // Uniform location buffer map std::map uniforms; @@ -248,8 +254,8 @@ private: static StringMap uniformTypes; // Names for the generic vertex attributes used by love. - static StringMap::Entry attribNameEntries[]; - static StringMap attribNames; + static StringMap::Entry attribNameEntries[]; + static StringMap attribNames; // Names for the built-in uniform variables. static StringMap::Entry builtinNameEntries[]; diff --git a/src/modules/graphics/opengl/SpriteBatch.cpp b/src/modules/graphics/opengl/SpriteBatch.cpp index 5d578e023..c60f3dcc8 100644 --- a/src/modules/graphics/opengl/SpriteBatch.cpp +++ b/src/modules/graphics/opengl/SpriteBatch.cpp @@ -283,25 +283,25 @@ void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float // Apply per-sprite color, if a color is set. if (color) { - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), array_buf->getPointer(color_offset)); + glEnableVertexAttribArray(ATTRIB_COLOR); + glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), array_buf->getPointer(color_offset)); } - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, sizeof(Vertex), array_buf->getPointer(pos_offset)); + glEnableVertexAttribArray(ATTRIB_POS); + glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), array_buf->getPointer(pos_offset)); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), array_buf->getPointer(texel_offset)); + glEnableVertexAttribArray(ATTRIB_TEXCOORD); + glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), array_buf->getPointer(texel_offset)); gl.prepareDraw(); gl.drawElements(GL_TRIANGLES, element_buf->getIndexCount(next), element_buf->getType(), element_buf->getPointer(0)); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableVertexAttribArray(ATTRIB_TEXCOORD); + glDisableVertexAttribArray(ATTRIB_POS); if (color) { - glDisableClientState(GL_COLOR_ARRAY); + glDisableVertexAttribArray(ATTRIB_COLOR); gl.setColor(curcolor); } diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index b1c818e30..ee82661f0 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -960,6 +960,26 @@ int w_getShader(lua_State *L) return 1; } +int w_setDefaultShaderCode(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_getfield(L, 1, "opengl"); + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -2, 2); + + Shader::ShaderSources openglcode; + openglcode[Shader::TYPE_VERTEX] = luax_checkstring(L, -2); + openglcode[Shader::TYPE_PIXEL] = luax_checkstring(L, -1); + + lua_pop(L, 3); + + Shader::defaultCode[0] = openglcode; + + return 0; +} + + int w_getSupported(lua_State *L) { lua_createtable(L, 0, (int) Graphics::SUPPORT_MAX_ENUM); @@ -1438,6 +1458,7 @@ static const luaL_Reg functions[] = { "setShader", w_setShader }, { "getShader", w_getShader }, + { "_setDefaultShaderCode", w_setDefaultShaderCode }, { "getSupported", w_getSupported }, { "getCanvasFormats", w_getCanvasFormats }, diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index f20c1285f..26a3f3e36 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -89,6 +89,7 @@ int w_setCanvas(lua_State *L); int w_getCanvas(lua_State *L); int w_setShader(lua_State *L); int w_getShader(lua_State *L); +int w_setDefaultShaderCode(lua_State *L); int w_getSupported(lua_State *L); int w_getCanvasFormats(lua_State *L); int w_getCompressedImageFormats(lua_State *L); diff --git a/src/scripts/graphics.lua b/src/scripts/graphics.lua index 95bb8f236..90b45ef86 100644 --- a/src/scripts/graphics.lua +++ b/src/scripts/graphics.lua @@ -1310,12 +1310,12 @@ uniform vec4 love_ScreenSize;]] HEADER = [[ #define VERTEX -#define VertexPosition gl_Vertex -#define VertexTexCoord gl_MultiTexCoord0 -#define VertexColor gl_Color +attribute vec4 VertexPosition; +attribute vec4 VertexTexCoord; +attribute vec4 VertexColor; -#define VaryingTexCoord gl_TexCoord[0] -#define VaryingColor gl_FrontColor +varying vec4 VaryingTexCoord; +varying vec4 VaryingColor; // #if defined(GL_ARB_draw_instanced) // #extension GL_ARB_draw_instanced : enable @@ -1338,8 +1338,8 @@ void main() { HEADER = [[ #define PIXEL -#define VaryingTexCoord gl_TexCoord[0] -#define VaryingColor gl_Color]], +varying vec4 VaryingTexCoord; +varying vec4 VaryingColor;]], FOOTER = [[ void main() { @@ -1465,4 +1465,24 @@ void main() { if #lines == 1 then return message end return table_concat(lines, "\n") end + + local defaultcode = { + vertex = [[ +vec4 position(mat4 transform_proj, vec4 vertpos) { + return transform_proj * vertpos; +}]], + pixel = [[ +vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) { + return Texel(tex, texcoord) * vcolor; +}]] + } + + local defaults = { + opengl = { + createVertexCode(defaultcode.vertex), + createPixelCode(defaultcode.pixel, false), + }, + } + + love.graphics._setDefaultShaderCode(defaults) end diff --git a/src/scripts/graphics.lua.h b/src/scripts/graphics.lua.h index 6a3463cc6..064f69023 100644 --- a/src/scripts/graphics.lua.h +++ b/src/scripts/graphics.lua.h @@ -6301,18 +6301,16 @@ const unsigned char graphics_lua[] = 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x50, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x6c, 0x5f, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x54, 0x65, 0x78, 0x43, - 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x67, 0x6c, 0x5f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x54, 0x65, 0x78, 0x43, 0x6f, - 0x6f, 0x72, 0x64, 0x30, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x20, 0x67, 0x6c, 0x5f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x54, 0x65, 0x78, - 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x67, 0x6c, 0x5f, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x5b, - 0x30, 0x5d, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0a, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x65, 0x72, + 0x74, 0x65, 0x78, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x65, 0x72, + 0x74, 0x65, 0x78, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x65, 0x72, + 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, + 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, + 0x6e, 0x67, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, + 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, + 0x6e, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x2f, 0x2f, 0x20, 0x23, 0x69, 0x66, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x28, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x29, 0x0a, @@ -6347,11 +6345,10 @@ const unsigned char graphics_lua[] = 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x50, 0x49, 0x58, 0x45, 0x4c, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x54, 0x65, 0x78, - 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x67, 0x6c, 0x5f, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x5b, - 0x30, 0x5d, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x20, 0x67, 0x6c, 0x5f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x5d, 0x5d, 0x2c, 0x0a, + 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, + 0x6e, 0x67, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, + 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, + 0x6e, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x5d, 0x5d, 0x2c, 0x0a, 0x09, 0x09, 0x46, 0x4f, 0x4f, 0x54, 0x45, 0x52, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x66, 0x69, 0x78, 0x20, 0x63, 0x72, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x69, @@ -6610,6 +6607,39 @@ const unsigned char graphics_lua[] = 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x63, 0x6f, 0x64, 0x65, + 0x20, 0x3d, 0x20, 0x7b, 0x0a, + 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a, + 0x76, 0x65, 0x63, 0x34, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6d, 0x61, 0x74, 0x34, + 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x2c, 0x20, 0x76, + 0x65, 0x63, 0x34, 0x20, 0x76, 0x65, 0x72, 0x74, 0x70, 0x6f, 0x73, 0x29, 0x20, 0x7b, 0x0a, + 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x5f, + 0x70, 0x72, 0x6f, 0x6a, 0x20, 0x2a, 0x20, 0x76, 0x65, 0x72, 0x74, 0x70, 0x6f, 0x73, 0x3b, 0x0a, + 0x7d, 0x5d, 0x5d, 0x2c, 0x0a, + 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a, + 0x76, 0x65, 0x63, 0x34, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x28, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, + 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x74, 0x65, 0x78, 0x2c, 0x20, + 0x76, 0x65, 0x63, 0x32, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x76, 0x65, 0x63, + 0x32, 0x20, 0x70, 0x69, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x29, 0x20, 0x7b, 0x0a, + 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x54, 0x65, 0x78, 0x65, 0x6c, 0x28, 0x74, 0x65, 0x78, 0x2c, + 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x29, 0x20, 0x2a, 0x20, 0x76, 0x63, 0x6f, 0x6c, 0x6f, + 0x72, 0x3b, 0x0a, + 0x7d, 0x5d, 0x5d, 0x0a, + 0x09, 0x7d, 0x0a, + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x3d, 0x20, + 0x7b, 0x0a, + 0x09, 0x09, 0x6f, 0x70, 0x65, 0x6e, 0x67, 0x6c, 0x20, 0x3d, 0x20, 0x7b, 0x0a, + 0x09, 0x09, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x64, + 0x65, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x65, 0x72, 0x74, + 0x65, 0x78, 0x29, 0x2c, 0x0a, + 0x09, 0x09, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, + 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x69, 0x78, 0x65, 0x6c, + 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x2c, 0x0a, + 0x09, 0x09, 0x7d, 0x2c, 0x0a, + 0x09, 0x7d, 0x0a, + 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x5f, 0x73, 0x65, + 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, + 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a, }; // [graphics.lua] } // love