mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
Add Depth compare / shadow sampler support. Officially this is only supported in glsl3 shaders.
- Add Texture:setDepthSampleMode(comparemode). Only works on textures with depth pixel formats. A texture with the depth sample mode set will only work with a depth sampler. - Add DepthImage, DepthArrayImage, and DepthCubeImage sampler keywords to glsl3. --HG-- branch : minor
This commit is contained in:
@@ -475,6 +475,8 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT
|
||||
src/modules/graphics/Canvas.cpp
|
||||
src/modules/graphics/Canvas.h
|
||||
src/modules/graphics/Color.h
|
||||
src/modules/graphics/depthstencil.cpp
|
||||
src/modules/graphics/depthstencil.h
|
||||
src/modules/graphics/Drawable.cpp
|
||||
src/modules/graphics/Drawable.h
|
||||
src/modules/graphics/Font.cpp
|
||||
|
||||
@@ -1132,6 +1132,8 @@
|
||||
FAF140DB1E20934C00F898D2 /* InitializeDll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF1403B1E20934C00F898D2 /* InitializeDll.cpp */; };
|
||||
FAF140DC1E20934C00F898D2 /* InitializeDll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF1403B1E20934C00F898D2 /* InitializeDll.cpp */; };
|
||||
FAF140DD1E20934C00F898D2 /* InitializeDll.h in Headers */ = {isa = PBXBuildFile; fileRef = FAF1403C1E20934C00F898D2 /* InitializeDll.h */; };
|
||||
FAF1889F1E9DBC4B008C1479 /* depthstencil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF1889E1E9DBC4B008C1479 /* depthstencil.cpp */; };
|
||||
FAF188A01E9DBC4B008C1479 /* depthstencil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF1889E1E9DBC4B008C1479 /* depthstencil.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@@ -1937,6 +1939,8 @@
|
||||
FAF1403B1E20934C00F898D2 /* InitializeDll.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeDll.cpp; sourceTree = "<group>"; };
|
||||
FAF1403C1E20934C00F898D2 /* InitializeDll.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeDll.h; sourceTree = "<group>"; };
|
||||
FAF1889C1E9DA834008C1479 /* Optional.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Optional.h; sourceTree = "<group>"; };
|
||||
FAF1889D1E9DBBC8008C1479 /* depthstencil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = depthstencil.h; sourceTree = "<group>"; };
|
||||
FAF1889E1E9DBC4B008C1479 /* depthstencil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = depthstencil.cpp; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -2663,6 +2667,8 @@
|
||||
FA1BA0A51E16F20600AA2803 /* Canvas.cpp */,
|
||||
FA1BA0A61E16F20600AA2803 /* Canvas.h */,
|
||||
FA0B7B881A95902C000E1D17 /* Color.h */,
|
||||
FAF1889E1E9DBC4B008C1479 /* depthstencil.cpp */,
|
||||
FAF1889D1E9DBBC8008C1479 /* depthstencil.h */,
|
||||
FA9D8DDC1DEF842A002CD881 /* Drawable.cpp */,
|
||||
FA0B7B891A95902C000E1D17 /* Drawable.h */,
|
||||
FA1BA09B1E16CFCE00AA2803 /* Font.cpp */,
|
||||
@@ -4185,6 +4191,7 @@
|
||||
FA0B7DDD1A95902C000E1D17 /* wrap_BezierCurve.cpp in Sources */,
|
||||
FA0B7A2A1A958EA3000E1D17 /* b2BroadPhase.cpp in Sources */,
|
||||
FA0B7A811A958EA3000E1D17 /* b2EdgeAndCircleContact.cpp in Sources */,
|
||||
FAF188A01E9DBC4B008C1479 /* depthstencil.cpp in Sources */,
|
||||
FA0B7D071A95902C000E1D17 /* wrap_File.cpp in Sources */,
|
||||
FAD19A181DFF8CA200D5398A /* ImageDataBase.cpp in Sources */,
|
||||
FA0B7AD01A958EA3000E1D17 /* peer.c in Sources */,
|
||||
@@ -4545,6 +4552,7 @@
|
||||
FA0B7DDC1A95902C000E1D17 /* wrap_BezierCurve.cpp in Sources */,
|
||||
FA0B7A951A958EA3000E1D17 /* b2Joint.cpp in Sources */,
|
||||
FA0B7D061A95902C000E1D17 /* wrap_File.cpp in Sources */,
|
||||
FAF1889F1E9DBC4B008C1479 /* depthstencil.cpp in Sources */,
|
||||
FA0B7A4E1A958EA3000E1D17 /* b2Draw.cpp in Sources */,
|
||||
FAD19A171DFF8CA200D5398A /* ImageDataBase.cpp in Sources */,
|
||||
FA27B3C01B4985BF008A9DCE /* wrap_VideoStream.cpp in Sources */,
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
namespace love
|
||||
{
|
||||
|
||||
// Currently only meant for simple types.
|
||||
// Currently only meant for simple and small types.
|
||||
template <typename T>
|
||||
struct Optional
|
||||
{
|
||||
@@ -40,8 +40,11 @@ struct Optional
|
||||
, value(val)
|
||||
{}
|
||||
|
||||
private:
|
||||
|
||||
void set(T val)
|
||||
{
|
||||
hasValue = true;
|
||||
value = val;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Optional<bool> OptionalBool;
|
||||
|
||||
@@ -125,6 +125,12 @@ bool isPixelFormatDepthStencil(PixelFormat format)
|
||||
return iformat >= (int) PIXELFORMAT_STENCIL8 && iformat <= (int) PIXELFORMAT_DEPTH32F_STENCIL8;
|
||||
}
|
||||
|
||||
bool isPixelFormatDepth(PixelFormat format)
|
||||
{
|
||||
int iformat = (int) format;
|
||||
return iformat >= (int) PIXELFORMAT_DEPTH16 && iformat <= (int) PIXELFORMAT_DEPTH32F_STENCIL8;
|
||||
}
|
||||
|
||||
size_t getPixelFormatSize(PixelFormat format)
|
||||
{
|
||||
switch (format)
|
||||
|
||||
@@ -115,10 +115,15 @@ bool getConstant(const char *in, PixelFormat &out);
|
||||
bool isPixelFormatCompressed(PixelFormat format);
|
||||
|
||||
/**
|
||||
* Gets whether the specified pixel format is a depth/stencil type.
|
||||
* Gets whether the specified pixel format is a depth or stencil type.
|
||||
**/
|
||||
bool isPixelFormatDepthStencil(PixelFormat format);
|
||||
|
||||
/**
|
||||
* Gets whether the specified pixel format is a depth type.
|
||||
**/
|
||||
bool isPixelFormatDepth(PixelFormat format);
|
||||
|
||||
/**
|
||||
* Gets the size in bytes of the specified pixel format.
|
||||
* NOTE: Currently returns 0 for compressed formats.
|
||||
|
||||
@@ -589,6 +589,9 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &
|
||||
|
||||
StreamBufferState &state = streamBufferState;
|
||||
|
||||
if (state.vertexCount == 0 && Shader::current != nullptr && req.texture != nullptr)
|
||||
Shader::current->checkMainTexture(req.texture);
|
||||
|
||||
bool shouldflush = false;
|
||||
bool shouldresize = false;
|
||||
|
||||
@@ -706,6 +709,13 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &
|
||||
return d;
|
||||
}
|
||||
|
||||
void Graphics::flushStreamDrawsGlobal()
|
||||
{
|
||||
Graphics *instance = getInstance<Graphics>(M_GRAPHICS);
|
||||
if (instance != nullptr)
|
||||
instance->flushStreamDraws();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drawing
|
||||
**/
|
||||
@@ -1266,26 +1276,6 @@ bool Graphics::getConstant(LineJoin in, const char *&out)
|
||||
return lineJoins.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(const char *in, StencilAction &out)
|
||||
{
|
||||
return stencilActions.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(StencilAction in, const char *&out)
|
||||
{
|
||||
return stencilActions.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(const char *in, CompareMode &out)
|
||||
{
|
||||
return compareModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(CompareMode in, const char *&out)
|
||||
{
|
||||
return compareModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(const char *in, Feature &out)
|
||||
{
|
||||
return features.find(in, out);
|
||||
@@ -1373,31 +1363,6 @@ StringMap<Graphics::LineJoin, Graphics::LINE_JOIN_MAX_ENUM>::Entry Graphics::lin
|
||||
|
||||
StringMap<Graphics::LineJoin, Graphics::LINE_JOIN_MAX_ENUM> Graphics::lineJoins(Graphics::lineJoinEntries, sizeof(Graphics::lineJoinEntries));
|
||||
|
||||
StringMap<Graphics::StencilAction, Graphics::STENCIL_MAX_ENUM>::Entry Graphics::stencilActionEntries[] =
|
||||
{
|
||||
{ "replace", STENCIL_REPLACE },
|
||||
{ "increment", STENCIL_INCREMENT },
|
||||
{ "decrement", STENCIL_DECREMENT },
|
||||
{ "incrementwrap", STENCIL_INCREMENT_WRAP },
|
||||
{ "decrementwrap", STENCIL_DECREMENT_WRAP },
|
||||
{ "invert", STENCIL_INVERT },
|
||||
};
|
||||
|
||||
StringMap<Graphics::StencilAction, Graphics::STENCIL_MAX_ENUM> Graphics::stencilActions(Graphics::stencilActionEntries, sizeof(Graphics::stencilActionEntries));
|
||||
|
||||
StringMap<Graphics::CompareMode, Graphics::COMPARE_MAX_ENUM>::Entry Graphics::compareModeEntries[] =
|
||||
{
|
||||
{ "less", COMPARE_LESS },
|
||||
{ "lequal", COMPARE_LEQUAL },
|
||||
{ "equal", COMPARE_EQUAL },
|
||||
{ "gequal", COMPARE_GEQUAL },
|
||||
{ "greater", COMPARE_GREATER },
|
||||
{ "notequal", COMPARE_NOTEQUAL },
|
||||
{ "always", COMPARE_ALWAYS },
|
||||
};
|
||||
|
||||
StringMap<Graphics::CompareMode, Graphics::COMPARE_MAX_ENUM> Graphics::compareModes(Graphics::compareModeEntries, sizeof(Graphics::compareModeEntries));
|
||||
|
||||
StringMap<Graphics::Feature, Graphics::FEATURE_MAX_ENUM>::Entry Graphics::featureEntries[] =
|
||||
{
|
||||
{ "multicanvasformats", FEATURE_MULTI_CANVAS_FORMATS },
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "Quad.h"
|
||||
#include "Mesh.h"
|
||||
#include "Image.h"
|
||||
#include "depthstencil.h"
|
||||
#include "math/Transform.h"
|
||||
#include "font/Rasterizer.h"
|
||||
#include "video/VideoStream.h"
|
||||
@@ -150,29 +151,6 @@ public:
|
||||
LINE_JOIN_MAX_ENUM
|
||||
};
|
||||
|
||||
enum StencilAction
|
||||
{
|
||||
STENCIL_REPLACE,
|
||||
STENCIL_INCREMENT,
|
||||
STENCIL_DECREMENT,
|
||||
STENCIL_INCREMENT_WRAP,
|
||||
STENCIL_DECREMENT_WRAP,
|
||||
STENCIL_INVERT,
|
||||
STENCIL_MAX_ENUM
|
||||
};
|
||||
|
||||
enum CompareMode
|
||||
{
|
||||
COMPARE_LESS,
|
||||
COMPARE_LEQUAL,
|
||||
COMPARE_EQUAL,
|
||||
COMPARE_GEQUAL,
|
||||
COMPARE_GREATER,
|
||||
COMPARE_NOTEQUAL,
|
||||
COMPARE_ALWAYS,
|
||||
COMPARE_MAX_ENUM
|
||||
};
|
||||
|
||||
enum Feature
|
||||
{
|
||||
FEATURE_MULTI_CANVAS_FORMATS,
|
||||
@@ -761,6 +739,8 @@ public:
|
||||
virtual void flushStreamDraws() = 0;
|
||||
StreamVertexData requestStreamDraw(const StreamDrawRequest &request);
|
||||
|
||||
static void flushStreamDrawsGlobal();
|
||||
|
||||
virtual Shader::Language getShaderLanguageTarget() const = 0;
|
||||
const Shader::ShaderSource &getCurrentDefaultShaderCode() const;
|
||||
|
||||
@@ -793,12 +773,6 @@ public:
|
||||
static bool getConstant(const char *in, LineJoin &out);
|
||||
static bool getConstant(LineJoin in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, StencilAction &out);
|
||||
static bool getConstant(StencilAction in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, CompareMode &out);
|
||||
static bool getConstant(CompareMode in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, Feature &out);
|
||||
static bool getConstant(Feature in, const char *&out);
|
||||
|
||||
@@ -932,12 +906,6 @@ private:
|
||||
static StringMap<LineJoin, LINE_JOIN_MAX_ENUM>::Entry lineJoinEntries[];
|
||||
static StringMap<LineJoin, LINE_JOIN_MAX_ENUM> lineJoins;
|
||||
|
||||
static StringMap<StencilAction, STENCIL_MAX_ENUM>::Entry stencilActionEntries[];
|
||||
static StringMap<StencilAction, STENCIL_MAX_ENUM> stencilActions;
|
||||
|
||||
static StringMap<CompareMode, COMPARE_MAX_ENUM>::Entry compareModeEntries[];
|
||||
static StringMap<CompareMode, COMPARE_MAX_ENUM> compareModes;
|
||||
|
||||
static StringMap<Feature, FEATURE_MAX_ENUM>::Entry featureEntries[];
|
||||
static StringMap<Feature, FEATURE_MAX_ENUM> features;
|
||||
|
||||
|
||||
@@ -192,11 +192,14 @@ TextureType Shader::getMainTextureType() const
|
||||
return info != nullptr ? info->textureType : TEXTURE_MAX_ENUM;
|
||||
}
|
||||
|
||||
void Shader::checkMainTextureType(TextureType textype) const
|
||||
void Shader::checkMainTextureType(TextureType textype, bool isDepthSampler) const
|
||||
{
|
||||
const UniformInfo *info = getUniformInfo(BUILTIN_TEXTURE_MAIN);
|
||||
|
||||
if (info != nullptr && info->textureType != TEXTURE_MAX_ENUM && info->textureType != textype)
|
||||
if (info == nullptr)
|
||||
return;
|
||||
|
||||
if (info->textureType != TEXTURE_MAX_ENUM && info->textureType != textype)
|
||||
{
|
||||
const char *textypestr = "unknown";
|
||||
const char *shadertextypestr = "unknown";
|
||||
@@ -204,14 +207,22 @@ void Shader::checkMainTextureType(TextureType textype) const
|
||||
Texture::getConstant(info->textureType, shadertextypestr);
|
||||
throw love::Exception("Texture's type (%s) must match the type of the shader's main texture type (%s).", textypestr, shadertextypestr);
|
||||
}
|
||||
|
||||
if (info->isDepthSampler != isDepthSampler)
|
||||
{
|
||||
if (info->isDepthSampler)
|
||||
throw love::Exception("Depth comparison samplers in shaders can only be used with depth textures which have depth comparison set.");
|
||||
else
|
||||
throw love::Exception("Depth textures which have depth comparison set can only be used with depth/shadow samplers in shaders.");
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::checkMainTexture(Texture *texture) const
|
||||
void Shader::checkMainTexture(Texture *tex) const
|
||||
{
|
||||
if (!texture->isReadable())
|
||||
if (!tex->isReadable())
|
||||
throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader.");
|
||||
|
||||
checkMainTextureType(texture->getTextureType());
|
||||
checkMainTextureType(tex->getTextureType(), tex->getDepthSampleMode().hasValue);
|
||||
}
|
||||
|
||||
bool Shader::validate(Graphics *gfx, bool gles, const ShaderSource &source, bool checkWithDefaults, std::string &err)
|
||||
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
|
||||
UniformType baseType;
|
||||
TextureType textureType;
|
||||
bool isDepthTexture;
|
||||
bool isDepthSampler;
|
||||
std::string name;
|
||||
|
||||
union
|
||||
@@ -190,7 +190,7 @@ public:
|
||||
virtual void setVideoTextures(Texture *ytexture, Texture *cbtexture, Texture *crtexture) = 0;
|
||||
|
||||
TextureType getMainTextureType() const;
|
||||
void checkMainTextureType(TextureType textype) const;
|
||||
void checkMainTextureType(TextureType textype, bool isDepthSampler) const;
|
||||
void checkMainTexture(Texture *texture) const;
|
||||
|
||||
virtual ptrdiff_t getHandle() const = 0;
|
||||
|
||||
@@ -230,6 +230,17 @@ float Texture::getMipmapSharpness() const
|
||||
return mipmapSharpness;
|
||||
}
|
||||
|
||||
void Texture::setDepthSampleMode(Optional<CompareMode> mode)
|
||||
{
|
||||
if (mode.hasValue && (!readable || !isPixelFormatDepthStencil(format)))
|
||||
throw love::Exception("Only readable depth textures can have a depth sample compare mode.");
|
||||
}
|
||||
|
||||
Optional<CompareMode> Texture::getDepthSampleMode() const
|
||||
{
|
||||
return depthCompareMode;
|
||||
}
|
||||
|
||||
Quad *Texture::getQuad() const
|
||||
{
|
||||
return quad;
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
#include "common/math.h"
|
||||
#include "common/pixelformat.h"
|
||||
#include "common/Exception.h"
|
||||
#include "common/Optional.h"
|
||||
#include "Drawable.h"
|
||||
#include "Quad.h"
|
||||
#include "vertex.h"
|
||||
#include "depthstencil.h"
|
||||
|
||||
// C
|
||||
#include <stddef.h>
|
||||
@@ -143,6 +145,9 @@ public:
|
||||
virtual bool setMipmapSharpness(float sharpness) = 0;
|
||||
float getMipmapSharpness() const;
|
||||
|
||||
virtual void setDepthSampleMode(Optional<CompareMode> mode = Optional<CompareMode>());
|
||||
Optional<CompareMode> getDepthSampleMode() const;
|
||||
|
||||
Quad *getQuad() const;
|
||||
|
||||
virtual ptrdiff_t getHandle() const = 0;
|
||||
@@ -185,6 +190,8 @@ protected:
|
||||
|
||||
float mipmapSharpness;
|
||||
|
||||
Optional<CompareMode> depthCompareMode;
|
||||
|
||||
StrongRef<Quad> quad;
|
||||
|
||||
private:
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2017 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "depthstencil.h"
|
||||
#include "common/StringMap.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
CompareMode getReversedCompareMode(CompareMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case COMPARE_LESS:
|
||||
return COMPARE_GREATER;
|
||||
case COMPARE_LEQUAL:
|
||||
return COMPARE_GEQUAL;
|
||||
case COMPARE_EQUAL:
|
||||
return COMPARE_EQUAL;
|
||||
case COMPARE_GEQUAL:
|
||||
return COMPARE_LEQUAL;
|
||||
case COMPARE_GREATER:
|
||||
return COMPARE_LESS;
|
||||
case COMPARE_NOTEQUAL:
|
||||
return COMPARE_NOTEQUAL;
|
||||
case COMPARE_ALWAYS:
|
||||
return COMPARE_ALWAYS;
|
||||
case COMPARE_MAX_ENUM:
|
||||
default:
|
||||
return COMPARE_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
|
||||
static StringMap<StencilAction, STENCIL_MAX_ENUM>::Entry stencilActionEntries[] =
|
||||
{
|
||||
{ "replace", STENCIL_REPLACE },
|
||||
{ "increment", STENCIL_INCREMENT },
|
||||
{ "decrement", STENCIL_DECREMENT },
|
||||
{ "incrementwrap", STENCIL_INCREMENT_WRAP },
|
||||
{ "decrementwrap", STENCIL_DECREMENT_WRAP },
|
||||
{ "invert", STENCIL_INVERT },
|
||||
};
|
||||
|
||||
static StringMap<StencilAction, STENCIL_MAX_ENUM> stencilActions(stencilActionEntries, sizeof(stencilActionEntries));
|
||||
|
||||
static StringMap<CompareMode, COMPARE_MAX_ENUM>::Entry compareModeEntries[] =
|
||||
{
|
||||
{ "less", COMPARE_LESS },
|
||||
{ "lequal", COMPARE_LEQUAL },
|
||||
{ "equal", COMPARE_EQUAL },
|
||||
{ "gequal", COMPARE_GEQUAL },
|
||||
{ "greater", COMPARE_GREATER },
|
||||
{ "notequal", COMPARE_NOTEQUAL },
|
||||
{ "always", COMPARE_ALWAYS },
|
||||
};
|
||||
|
||||
static StringMap<CompareMode, COMPARE_MAX_ENUM> compareModes(compareModeEntries, sizeof(compareModeEntries));
|
||||
|
||||
bool getConstant(const char *in, StencilAction &out)
|
||||
{
|
||||
return stencilActions.find(in, out);
|
||||
}
|
||||
|
||||
bool getConstant(StencilAction in, const char *&out)
|
||||
{
|
||||
return stencilActions.find(in, out);
|
||||
}
|
||||
|
||||
bool getConstant(const char *in, CompareMode &out)
|
||||
{
|
||||
return compareModes.find(in, out);
|
||||
}
|
||||
|
||||
bool getConstant(CompareMode in, const char *&out)
|
||||
{
|
||||
return compareModes.find(in, out);
|
||||
}
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2017 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
enum StencilAction
|
||||
{
|
||||
STENCIL_REPLACE,
|
||||
STENCIL_INCREMENT,
|
||||
STENCIL_DECREMENT,
|
||||
STENCIL_INCREMENT_WRAP,
|
||||
STENCIL_DECREMENT_WRAP,
|
||||
STENCIL_INVERT,
|
||||
STENCIL_MAX_ENUM
|
||||
};
|
||||
|
||||
enum CompareMode
|
||||
{
|
||||
COMPARE_LESS,
|
||||
COMPARE_LEQUAL,
|
||||
COMPARE_EQUAL,
|
||||
COMPARE_GEQUAL,
|
||||
COMPARE_GREATER,
|
||||
COMPARE_NOTEQUAL,
|
||||
COMPARE_ALWAYS,
|
||||
COMPARE_MAX_ENUM
|
||||
};
|
||||
|
||||
/**
|
||||
* GPU APIs do the comparison in the opposite way of what makes sense for some
|
||||
* of love's APIs. For example in OpenGL if the compare function is GL_GREATER,
|
||||
* then the stencil test will pass if the reference value is greater than the
|
||||
* value in the stencil buffer. With our stencil API it's more intuitive to
|
||||
* assume that setStencilTest(COMPARE_GREATER, 4) will make it pass if the
|
||||
* stencil buffer has a value greater than 4.
|
||||
**/
|
||||
CompareMode getReversedCompareMode(CompareMode mode);
|
||||
|
||||
bool getConstant(const char *in, StencilAction &out);
|
||||
bool getConstant(StencilAction in, const char *&out);
|
||||
|
||||
bool getConstant(const char *in, CompareMode &out);
|
||||
bool getConstant(CompareMode in, const char *&out);
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -277,6 +277,7 @@ bool Canvas::loadVolatile()
|
||||
|
||||
setFilter(filter);
|
||||
setWrap(wrap);
|
||||
setDepthSampleMode(depthCompareMode);
|
||||
|
||||
while (glGetError() != GL_NO_ERROR)
|
||||
/* Clear the error buffer. */;
|
||||
@@ -358,6 +359,8 @@ void Canvas::setFilter(const Texture::Filter &f)
|
||||
if (!validateFilter(f, false))
|
||||
throw love::Exception("Invalid texture filter.");
|
||||
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
filter = f;
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
gl.setTextureFilter(texType, filter);
|
||||
@@ -365,6 +368,8 @@ void Canvas::setFilter(const Texture::Filter &f)
|
||||
|
||||
bool Canvas::setWrap(const Texture::Wrap &w)
|
||||
{
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
bool success = true;
|
||||
bool forceclamp = texType == TEXTURE_CUBE;
|
||||
wrap = w;
|
||||
@@ -402,6 +407,42 @@ bool Canvas::setMipmapSharpness(float /*sharpness*/)
|
||||
return false;
|
||||
}
|
||||
|
||||
void Canvas::setDepthSampleMode(Optional<CompareMode> mode)
|
||||
{
|
||||
Texture::setDepthSampleMode(mode);
|
||||
|
||||
bool supported = gl.isDepthCompareSampleSupported();
|
||||
|
||||
if (mode.hasValue && !supported)
|
||||
throw love::Exception("Depth comparison sampling in shaders is not supported on this system.");
|
||||
|
||||
if (mode.hasValue)
|
||||
{
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
gl.bindTextureToUnit(texType, texture, 0, false);
|
||||
GLenum gltextype = OpenGL::getGLTextureType(texType);
|
||||
|
||||
// See the comment in depthstencil.h
|
||||
GLenum glmode = OpenGL::getGLCompareMode(getReversedCompareMode(mode.value));
|
||||
|
||||
glTexParameteri(gltextype, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
glTexParameteri(gltextype, GL_TEXTURE_COMPARE_FUNC, glmode);
|
||||
|
||||
}
|
||||
else if (isPixelFormatDepth(format) && supported)
|
||||
{
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
gl.bindTextureToUnit(texType, texture, 0, false);
|
||||
GLenum gltextype = OpenGL::getGLTextureType(texType);
|
||||
|
||||
glTexParameteri(gltextype, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
}
|
||||
|
||||
depthCompareMode = mode;
|
||||
}
|
||||
|
||||
ptrdiff_t Canvas::getHandle() const
|
||||
{
|
||||
return texture;
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
void setFilter(const Texture::Filter &f) override;
|
||||
bool setWrap(const Texture::Wrap &w) override;
|
||||
bool setMipmapSharpness(float sharpness) override;
|
||||
void setDepthSampleMode(Optional<CompareMode> mode) override;
|
||||
ptrdiff_t getHandle() const override;
|
||||
|
||||
love::image::ImageData *newImageData(love::image::Image *module, int slice, int x, int y, int w, int h) override;
|
||||
|
||||
@@ -354,12 +354,6 @@ void Graphics::flushStreamDraws()
|
||||
prevdefaultshader = Shader::current;
|
||||
Shader::standardShaders[Shader::STANDARD_ARRAY]->attach();
|
||||
}
|
||||
|
||||
if (!sbstate.texture->isReadable())
|
||||
throw love::Exception("Textures with non-readable formats cannot be drawn.");
|
||||
|
||||
if (Shader::current)
|
||||
Shader::current->checkMainTextureType(textype);
|
||||
}
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("Stream vertices flush and draw");
|
||||
@@ -1236,45 +1230,15 @@ void Graphics::setStencilTest(CompareMode compare, int value)
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum glcompare = GL_EQUAL;
|
||||
|
||||
/**
|
||||
* Q: Why are some of the compare modes inverted (e.g. COMPARE_LESS becomes
|
||||
* GL_GREATER)?
|
||||
*
|
||||
* A: OpenGL / GPUs do the comparison in the opposite way that makes sense
|
||||
* OpenGL / GPUs do the comparison in the opposite way that makes sense
|
||||
* for this API. For example, if the compare function is GL_GREATER then the
|
||||
* stencil test will pass if the reference value is greater than the value
|
||||
* in the stencil buffer. With our API it's more intuitive to assume that
|
||||
* setStencilTest(COMPARE_GREATER, 4) will make it pass if the stencil
|
||||
* buffer has a value greater than 4.
|
||||
**/
|
||||
|
||||
switch (compare)
|
||||
{
|
||||
case COMPARE_LESS:
|
||||
glcompare = GL_GREATER;
|
||||
break;
|
||||
case COMPARE_LEQUAL:
|
||||
glcompare = GL_GEQUAL;
|
||||
break;
|
||||
case COMPARE_EQUAL:
|
||||
default:
|
||||
glcompare = GL_EQUAL;
|
||||
break;
|
||||
case COMPARE_GEQUAL:
|
||||
glcompare = GL_LEQUAL;
|
||||
break;
|
||||
case COMPARE_GREATER:
|
||||
glcompare = GL_LESS;
|
||||
break;
|
||||
case COMPARE_NOTEQUAL:
|
||||
glcompare = GL_NOTEQUAL;
|
||||
break;
|
||||
case COMPARE_ALWAYS:
|
||||
glcompare = GL_ALWAYS;
|
||||
break;
|
||||
}
|
||||
GLenum glcompare = OpenGL::getGLCompareMode(getReversedCompareMode(compare));
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(glcompare, value, 0xFFFFFFFF);
|
||||
|
||||
@@ -380,6 +380,8 @@ void Image::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap,
|
||||
if (w != oldd->getWidth() || h != oldd->getHeight())
|
||||
throw love::Exception("Dimensions must match the texture's dimensions for the specified mipmap level.");
|
||||
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
d->retain();
|
||||
oldd->release();
|
||||
|
||||
@@ -397,6 +399,8 @@ void Image::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap,
|
||||
|
||||
void Image::replacePixels(const void *data, size_t size, const Rect &rect, int slice, int mipmap, bool reloadmipmaps)
|
||||
{
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("Image replace pixels");
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
@@ -422,6 +426,8 @@ void Image::setFilter(const Texture::Filter &f)
|
||||
throw love::Exception("Invalid texture filter.");
|
||||
}
|
||||
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
filter = f;
|
||||
|
||||
if (!OpenGL::hasTextureFilteringSupport(getPixelFormat()))
|
||||
@@ -445,6 +451,8 @@ void Image::setFilter(const Texture::Filter &f)
|
||||
|
||||
bool Image::setWrap(const Texture::Wrap &w)
|
||||
{
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
bool success = true;
|
||||
bool forceclamp = texType == TEXTURE_CUBE;
|
||||
wrap = w;
|
||||
@@ -483,6 +491,8 @@ bool Image::setMipmapSharpness(float sharpness)
|
||||
if (!GLAD_VERSION_1_4)
|
||||
return false;
|
||||
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
// LOD bias has the range (-maxbias, maxbias)
|
||||
mipmapSharpness = std::min(std::max(sharpness, -maxMipmapSharpness + 0.01f), maxMipmapSharpness - 0.01f);
|
||||
|
||||
|
||||
@@ -987,6 +987,29 @@ GLint OpenGL::getGLWrapMode(Texture::WrapMode wmode)
|
||||
|
||||
}
|
||||
|
||||
GLint OpenGL::getGLCompareMode(CompareMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case COMPARE_LESS:
|
||||
return GL_LESS;
|
||||
case COMPARE_LEQUAL:
|
||||
return GL_LEQUAL;
|
||||
case COMPARE_EQUAL:
|
||||
return GL_EQUAL;
|
||||
case COMPARE_GEQUAL:
|
||||
return GL_GEQUAL;
|
||||
case COMPARE_GREATER:
|
||||
return GL_GREATER;
|
||||
case COMPARE_NOTEQUAL:
|
||||
return GL_NOTEQUAL;
|
||||
case COMPARE_ALWAYS:
|
||||
return GL_ALWAYS;
|
||||
default:
|
||||
return GL_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGL::setTextureWrap(TextureType target, const graphics::Texture::Wrap &w)
|
||||
{
|
||||
glTexParameteri(getGLTextureType(target), GL_TEXTURE_WRAP_S, getGLWrapMode(w.s));
|
||||
@@ -1108,6 +1131,13 @@ bool OpenGL::isInstancingSupported() const
|
||||
|| GLAD_ARB_instanced_arrays || GLAD_EXT_instanced_arrays || GLAD_ANGLE_instanced_arrays;
|
||||
}
|
||||
|
||||
bool OpenGL::isDepthCompareSampleSupported() const
|
||||
{
|
||||
// Our official API only supports this in GLSL3 shaders, but unofficially
|
||||
// the requirements are more lax.
|
||||
return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_EXT_shadow_samplers;
|
||||
}
|
||||
|
||||
int OpenGL::getMax2DTextureSize() const
|
||||
{
|
||||
return std::max(max2DTextureSize, 1);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "graphics/Color.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/vertex.h"
|
||||
#include "graphics/depthstencil.h"
|
||||
#include "common/Matrix.h"
|
||||
|
||||
// GLAD
|
||||
@@ -326,6 +327,7 @@ public:
|
||||
bool isClampZeroTextureWrapSupported() const;
|
||||
bool isPixelShaderHighpSupported() const;
|
||||
bool isInstancingSupported() const;
|
||||
bool isDepthCompareSampleSupported() const;
|
||||
|
||||
/**
|
||||
* Returns the maximum supported width or height of a texture.
|
||||
@@ -379,6 +381,7 @@ public:
|
||||
static GLenum getGLBufferUsage(vertex::Usage usage);
|
||||
static GLenum getGLTextureType(TextureType type);
|
||||
static GLint getGLWrapMode(Texture::WrapMode wmode);
|
||||
static GLint getGLCompareMode(CompareMode mode);
|
||||
|
||||
static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB);
|
||||
static bool isTexStorageSupported();
|
||||
|
||||
@@ -173,6 +173,7 @@ void Shader::mapActiveUniforms()
|
||||
u.location = glGetUniformLocation(program, u.name.c_str());
|
||||
u.baseType = getUniformBaseType(gltype);
|
||||
u.textureType = getUniformTextureType(gltype);
|
||||
u.isDepthSampler = isDepthTextureType(gltype);
|
||||
|
||||
if (u.baseType == UNIFORM_MATRIX)
|
||||
u.matrix = getMatrixSize(gltype);
|
||||
@@ -675,22 +676,51 @@ void Shader::sendTextures(const UniformInfo *info, Texture **textures, int count
|
||||
// Bind the textures to the texture units.
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (textures[i] != nullptr)
|
||||
{
|
||||
if (textures[i]->getTextureType() != info->textureType || !textures[i]->isReadable())
|
||||
continue;
|
||||
Texture *tex = textures[i];
|
||||
|
||||
textures[i]->retain();
|
||||
if (tex != nullptr)
|
||||
{
|
||||
if (!tex->isReadable())
|
||||
{
|
||||
if (internalUpdate)
|
||||
continue;
|
||||
else
|
||||
throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader.");
|
||||
}
|
||||
else if (info->isDepthSampler != tex->getDepthSampleMode().hasValue)
|
||||
{
|
||||
if (internalUpdate)
|
||||
continue;
|
||||
else if (info->isDepthSampler)
|
||||
throw love::Exception("Depth comparison samplers in shaders can only be used with depth textures which have depth comparison set.");
|
||||
else
|
||||
throw love::Exception("Depth textures which have depth comparison set can only be used with depth/shadow samplers in shaders.");
|
||||
}
|
||||
else if (tex->getTextureType() != info->textureType)
|
||||
{
|
||||
if (internalUpdate)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
const char *textypestr = "unknown";
|
||||
const char *shadertextypestr = "unknown";
|
||||
Texture::getConstant(tex->getTextureType(), textypestr);
|
||||
Texture::getConstant(info->textureType, shadertextypestr);
|
||||
throw love::Exception("Texture's type (%s) must match the type of %s (%s).", textypestr, info->name.c_str(), shadertextypestr);
|
||||
}
|
||||
}
|
||||
|
||||
tex->retain();
|
||||
}
|
||||
|
||||
if (info->textures[i] != nullptr)
|
||||
info->textures[i]->release();
|
||||
|
||||
info->textures[i] = textures[i];
|
||||
info->textures[i] = tex;
|
||||
|
||||
GLuint gltex = 0;
|
||||
if (textures[i] != nullptr)
|
||||
gltex = (GLuint) textures[i]->getHandle();
|
||||
gltex = (GLuint) tex->getHandle();
|
||||
else
|
||||
gltex = gl.getDefaultTexture(info->textureType);
|
||||
|
||||
@@ -707,11 +737,7 @@ void Shader::sendTextures(const UniformInfo *info, Texture **textures, int count
|
||||
void Shader::flushStreamDraws() const
|
||||
{
|
||||
if (current == this)
|
||||
{
|
||||
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr)
|
||||
gfx->flushStreamDraws();
|
||||
}
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
}
|
||||
|
||||
bool Shader::hasUniform(const std::string &name) const
|
||||
@@ -1035,7 +1061,7 @@ TextureType Shader::getUniformTextureType(GLenum type) const
|
||||
// 1D-typed textures are not supported.
|
||||
return TEXTURE_MAX_ENUM;
|
||||
case GL_SAMPLER_2D:
|
||||
//case GL_SAMPLER_2D_SHADOW:
|
||||
case GL_SAMPLER_2D_SHADOW:
|
||||
return TEXTURE_2D;
|
||||
case GL_SAMPLER_2D_MULTISAMPLE:
|
||||
case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
|
||||
@@ -1046,12 +1072,12 @@ TextureType Shader::getUniformTextureType(GLenum type) const
|
||||
// Rectangle textures are not supported.
|
||||
return TEXTURE_MAX_ENUM;
|
||||
case GL_SAMPLER_2D_ARRAY:
|
||||
//case GL_SAMPLER_2D_ARRAY_SHADOW:
|
||||
case GL_SAMPLER_2D_ARRAY_SHADOW:
|
||||
return TEXTURE_2D_ARRAY;
|
||||
case GL_SAMPLER_3D:
|
||||
return TEXTURE_VOLUME;
|
||||
case GL_SAMPLER_CUBE:
|
||||
//case GL_SAMPLER_CUBE_SHADOW:
|
||||
case GL_SAMPLER_CUBE_SHADOW:
|
||||
return TEXTURE_CUBE;
|
||||
case GL_SAMPLER_CUBE_MAP_ARRAY:
|
||||
case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
|
||||
@@ -1062,6 +1088,22 @@ TextureType Shader::getUniformTextureType(GLenum type) const
|
||||
}
|
||||
}
|
||||
|
||||
bool Shader::isDepthTextureType(GLenum type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GL_SAMPLER_1D_SHADOW:
|
||||
case GL_SAMPLER_1D_ARRAY_SHADOW:
|
||||
case GL_SAMPLER_2D_SHADOW:
|
||||
case GL_SAMPLER_2D_ARRAY_SHADOW:
|
||||
case GL_SAMPLER_CUBE_SHADOW:
|
||||
case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
MatrixSize getMatrixSize(GLenum type) const;
|
||||
UniformType getUniformBaseType(GLenum type) const;
|
||||
TextureType getUniformTextureType(GLenum type) const;
|
||||
bool isDepthTextureType(GLenum type) const;
|
||||
|
||||
GLuint compileCode(ShaderStage stage, const std::string &code);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ void Text::draw(Graphics *gfx, const Matrix4 &m)
|
||||
return;
|
||||
|
||||
if (Shader::current)
|
||||
Shader::current->checkMainTextureType(TEXTURE_2D);
|
||||
Shader::current->checkMainTextureType(TEXTURE_2D, false);
|
||||
|
||||
gfx->flushStreamDraws();
|
||||
|
||||
|
||||
@@ -489,12 +489,12 @@ int w_stencil(lua_State *L)
|
||||
{
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
|
||||
Graphics::StencilAction action = Graphics::STENCIL_REPLACE;
|
||||
StencilAction action = STENCIL_REPLACE;
|
||||
|
||||
if (!lua_isnoneornil(L, 2))
|
||||
{
|
||||
const char *actionstr = luaL_checkstring(L, 2);
|
||||
if (!Graphics::getConstant(actionstr, action))
|
||||
if (!getConstant(actionstr, action))
|
||||
return luaL_error(L, "Invalid stencil draw action: %s", actionstr);
|
||||
}
|
||||
|
||||
@@ -522,13 +522,13 @@ int w_stencil(lua_State *L)
|
||||
int w_setStencilTest(lua_State *L)
|
||||
{
|
||||
// COMPARE_ALWAYS effectively disables stencil testing.
|
||||
Graphics::CompareMode compare = Graphics::COMPARE_ALWAYS;
|
||||
CompareMode compare = COMPARE_ALWAYS;
|
||||
int comparevalue = 0;
|
||||
|
||||
if (!lua_isnoneornil(L, 1))
|
||||
{
|
||||
const char *comparestr = luaL_checkstring(L, 1);
|
||||
if (!Graphics::getConstant(comparestr, compare))
|
||||
if (!getConstant(comparestr, compare))
|
||||
return luaL_error(L, "Invalid compare mode: %s", comparestr);
|
||||
|
||||
comparevalue = (int) luaL_checknumber(L, 2);
|
||||
@@ -540,13 +540,13 @@ int w_setStencilTest(lua_State *L)
|
||||
|
||||
int w_getStencilTest(lua_State *L)
|
||||
{
|
||||
Graphics::CompareMode compare = Graphics::COMPARE_ALWAYS;
|
||||
CompareMode compare = COMPARE_ALWAYS;
|
||||
int comparevalue = 1;
|
||||
|
||||
instance()->getStencilTest(compare, comparevalue);
|
||||
|
||||
const char *comparestr;
|
||||
if (!Graphics::getConstant(compare, comparestr))
|
||||
if (!getConstant(compare, comparestr))
|
||||
return luaL_error(L, "Unknown compare mode.");
|
||||
|
||||
lua_pushstring(L, comparestr);
|
||||
|
||||
@@ -50,6 +50,11 @@ GLSL.SYNTAX = [[
|
||||
#define ArrayImage sampler2DArray
|
||||
#define CubeImage samplerCube
|
||||
#define VolumeImage sampler3D
|
||||
#if __VERSION__ >= 300 && !defined(LOVE_GLSL1_ON_GLSL3)
|
||||
#define DepthImage sampler2DShadow
|
||||
#define DepthArrayImage sampler2DArrayShadow
|
||||
#define DepthCubeImage samplerCubeShadow
|
||||
#endif
|
||||
#define extern uniform
|
||||
#ifdef GL_EXT_texture_array
|
||||
#extension GL_EXT_texture_array : enable
|
||||
@@ -78,6 +83,11 @@ GLSL.FUNCTIONS = [[
|
||||
#if __VERSION__ >= 300 || defined(GL_OES_texture_3D)
|
||||
precision lowp sampler3D;
|
||||
#endif
|
||||
#if __VERSION__ >= 300
|
||||
precision lowp sampler2DShadow;
|
||||
precision lowp samplerCubeShadow;
|
||||
precision lowp sampler2DArrayShadow;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __VERSION__ >= 130 && !defined(LOVE_GLSL1_ON_GLSL3)
|
||||
|
||||
@@ -244,6 +244,42 @@ int w_Texture_isReadable(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Texture_setDepthSampleMode(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
|
||||
Optional<CompareMode> mode;
|
||||
if (!lua_isnoneornil(L, 2))
|
||||
{
|
||||
const char *str = luaL_checkstring(L, 2);
|
||||
|
||||
mode.hasValue = true;
|
||||
if (!getConstant(str, mode.value))
|
||||
return luaL_error(L, "Invalid compare mode: %s", str);
|
||||
}
|
||||
|
||||
luax_catchexcept(L, [&]() { t->setDepthSampleMode(mode); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Texture_getDepthSampleMode(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
Optional<CompareMode> mode = t->getDepthSampleMode();
|
||||
|
||||
if (mode.hasValue)
|
||||
{
|
||||
const char *str = nullptr;
|
||||
if (!getConstant(mode.value, str))
|
||||
return luaL_error(L, "Unknown compare mode.");
|
||||
lua_pushstring(L, str);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg w_Texture_functions[] =
|
||||
{
|
||||
{ "getTextureType", w_Texture_getTextureType },
|
||||
@@ -265,6 +301,8 @@ const luaL_Reg w_Texture_functions[] =
|
||||
{ "getWrap", w_Texture_getWrap },
|
||||
{ "getFormat", w_Texture_getFormat },
|
||||
{ "isReadable", w_Texture_isReadable },
|
||||
{ "getDepthSampleMode", w_Texture_getDepthSampleMode },
|
||||
{ "setDepthSampleMode", w_Texture_setDepthSampleMode },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user