diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 6e139b125..ca0a7ce3a 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -1516,6 +1516,75 @@ void Graphics::drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount) mesh->drawInstanced(this, m, instancecount); } +void Graphics::drawShaderVertices(PrimitiveType primtype, int vertexcount, int instancecount, Texture *maintexture) +{ + flushBatchedDraws(); + + if (!capabilities.features[FEATURE_GLSL3]) + throw love::Exception("drawShaderVertices is not supported on this system (GLSL3 support is required.)"); + + if (Shader::isDefaultActive() || !Shader::current) + throw love::Exception("drawShaderVertices can only be used with a custom shader."); + + if (vertexcount < 0 || instancecount < 0) + throw love::Exception("drawShaderVertices vertex and instance count parameters must not be negative."); + + Shader::current->validateDrawState(PRIMITIVE_TRIANGLES, maintexture); + + VertexAttributes attributes; + BufferBindings buffers; + + DrawCommand cmd(&attributes, &buffers); + + cmd.primitiveType = primtype; + cmd.vertexCount = vertexcount; + cmd.instanceCount = std::max(1, instancecount); + cmd.texture = maintexture; + + draw(cmd); +} + +void Graphics::drawShaderVertices(Buffer *indexbuffer, int indexcount, int instancecount, int startindex, Texture *maintexture) +{ + flushBatchedDraws(); + + if (!capabilities.features[FEATURE_GLSL3]) + throw love::Exception("drawShaderVertices is not supported on this system (GLSL3 support is required.)"); + + if (!(indexbuffer->getUsageFlags() & BUFFERUSAGEFLAG_INDEX)) + throw love::Exception("The buffer passed to drawShaderVertices must be an index buffer."); + + if (startindex < 0) + throw love::Exception("drawShaderVertices startindex parameter must not be negative."); + + if (indexcount < 0 || instancecount < 0) + throw love::Exception("drawShaderVertices index and instance count parameters must not be negative."); + + if ((size_t)(startindex + indexcount) > indexbuffer->getArrayLength()) + throw love::Exception("drawShaderVertices startindex and index count parameters do not fit in the given index buffer."); + + if (Shader::isDefaultActive() || !Shader::current) + throw love::Exception("drawShaderVertices can only be used with a custom shader."); + + Shader::current->validateDrawState(PRIMITIVE_TRIANGLES, maintexture); + + VertexAttributes attributes; + BufferBindings buffers; + + DrawIndexedCommand cmd(&attributes, &buffers, indexbuffer); + + cmd.primitiveType = PRIMITIVE_TRIANGLES; + cmd.indexCount = indexcount; + cmd.instanceCount = std::max(1, instancecount); + + cmd.indexType = getIndexDataType(indexbuffer->getDataMember(0).decl.format); + cmd.indexBufferOffset = startindex * getIndexDataSize(cmd.indexType); + + cmd.texture = maintexture; + + draw(cmd); +} + void Graphics::print(const std::vector &str, const Matrix4 &m) { checkSetDefaultFont(); diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index a614ea247..d666a3496 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -688,6 +688,9 @@ public: void drawLayer(Texture *texture, int layer, Quad *quad, const Matrix4 &m); void drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount); + void drawShaderVertices(PrimitiveType primtype, int vertexcount, int instancecount, Texture *maintexture); + void drawShaderVertices(Buffer *indexbuffer, int indexcount, int instancecount, int startindex, Texture *maintexture); + /** * Draws text at the specified coordinates **/ diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 56b83a4c8..c18be9940 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -2938,6 +2938,42 @@ int w_drawInstanced(lua_State *L) return 0; } +int w_drawShaderVertices(lua_State *L) +{ + if (luax_istype(L, 1, Buffer::type)) + { + // Indexed drawing. + Buffer *t = luax_checkbuffer(L, 1); + + int indexcount = (int) luaL_checkinteger(L, 2); + int instancecount = (int) luaL_optinteger(L, 3, 1); + int indexstart = (int) luaL_optinteger(L, 4, 1) - 1; + + Texture *tex = nullptr; + if (!lua_isnoneornil(L, 5)) + tex = luax_checktexture(L, 5); + + luax_catchexcept(L, [&]() { instance()->drawShaderVertices(t, indexcount, instancecount, indexstart, tex); }); + } + else + { + const char *primstr = luaL_checkstring(L, 1); + PrimitiveType primtype = PRIMITIVE_TRIANGLES; + if (!getConstant(primstr, primtype)) + return luax_enumerror(L, "primitive type", getConstants(primtype), primstr); + + int vertexcount = (int) luaL_checkinteger(L, 2); + int instancecount = (int) luaL_optinteger(L, 3, 1); + + Texture *tex = nullptr; + if (!lua_isnoneornil(L, 4)) + tex = luax_checktexture(L, 4); + + luax_catchexcept(L, [&]() { instance()->drawShaderVertices(primtype, vertexcount, instancecount, tex); }); + } + return 0; +} + int w_print(lua_State *L) { std::vector str; @@ -3614,6 +3650,7 @@ static const luaL_Reg functions[] = { "draw", w_draw }, { "drawLayer", w_drawLayer }, { "drawInstanced", w_drawInstanced }, + { "drawShaderVertices", w_drawShaderVertices }, { "print", w_print }, { "printf", w_printf },