Support for scaling splat textures in S and T, use mipmaps for them.

This commit is contained in:
Andrzej Kapolka 2014-08-22 16:43:09 -07:00
parent 4f3f0989f5
commit 2dfabdfe64
9 changed files with 71 additions and 11 deletions

View file

@ -11,6 +11,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
// the number of splats per pass
const int SPLAT_COUNT = 4; const int SPLAT_COUNT = 4;
// the splat textures // the splat textures
@ -22,7 +23,7 @@ varying vec4 alphaValues;
void main(void) { void main(void) {
// blend the splat textures // blend the splat textures
gl_FragColor = gl_Color * (texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x + gl_FragColor = gl_Color * (texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x +
texture2D(diffuseMaps[1], gl_TexCoord[0].st) * alphaValues.y + texture2D(diffuseMaps[1], gl_TexCoord[1].st) * alphaValues.y +
texture2D(diffuseMaps[2], gl_TexCoord[0].st) * alphaValues.z + texture2D(diffuseMaps[2], gl_TexCoord[2].st) * alphaValues.z +
texture2D(diffuseMaps[3], gl_TexCoord[0].st) * alphaValues.w); texture2D(diffuseMaps[3], gl_TexCoord[3].st) * alphaValues.w);
} }

View file

@ -23,6 +23,15 @@ uniform float heightScale;
// the scale between height and texture textures // the scale between height and texture textures
uniform float textureScale; uniform float textureScale;
// the splat texture offset
uniform vec2 splatTextureOffset;
// the splat textures scales on the S axis
uniform vec4 splatTextureScalesS;
// the splat texture scales on the T axis
uniform vec4 splatTextureScalesT;
// the lower bounds of the values corresponding to the splat textures // the lower bounds of the values corresponding to the splat textures
uniform vec4 textureValueMinima; uniform vec4 textureValueMinima;
@ -35,16 +44,21 @@ varying vec4 alphaValues;
void main(void) { void main(void) {
// add the height to the position // add the height to the position
float height = texture2D(heightMap, gl_MultiTexCoord0.st).r; float height = texture2D(heightMap, gl_MultiTexCoord0.st).r;
gl_Position = gl_ModelViewProjectionMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0)); vec4 modelSpacePosition = gl_Vertex + vec4(0.0, height, 0.0, 0.0);
gl_Position = gl_ModelViewProjectionMatrix * modelSpacePosition;
// the zero height should be invisible // the zero height should be invisible
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0 - step(height, 0.0)); gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0 - step(height, 0.0));
// pass along the scaled/offset texture coordinates // pass along the scaled/offset texture coordinates
gl_TexCoord[0] = (gl_MultiTexCoord0 - vec4(heightScale, heightScale, 0.0, 0.0)) * textureScale; vec4 textureSpacePosition = vec4(modelSpacePosition.xz, 0.0, 1.0) + vec4(splatTextureOffset, 0.0, 0.0);
gl_TexCoord[0] = textureSpacePosition * vec4(splatTextureScalesS[0], splatTextureScalesT[0], 0.0, 1.0);
gl_TexCoord[1] = textureSpacePosition * vec4(splatTextureScalesS[1], splatTextureScalesT[1], 0.0, 1.0);
gl_TexCoord[2] = textureSpacePosition * vec4(splatTextureScalesS[2], splatTextureScalesT[2], 0.0, 1.0);
gl_TexCoord[3] = textureSpacePosition * vec4(splatTextureScalesS[3], splatTextureScalesT[3], 0.0, 1.0);
// compute the alpha values for each texture // compute the alpha values for each texture
float value = texture2D(textureMap, gl_TexCoord[0].st).r; float value = texture2D(textureMap, (gl_MultiTexCoord0.st - vec2(heightScale, heightScale)) * textureScale).r;
vec4 valueVector = vec4(value, value, value, value); vec4 valueVector = vec4(value, value, value, value);
alphaValues = step(textureValueMinima, valueVector) * step(valueVector, textureValueMaxima); alphaValues = step(textureValueMinima, valueVector) * step(valueVector, textureValueMaxima);
} }

View file

@ -822,22 +822,38 @@ void HeightfieldBuffer::render(bool cursor) {
DefaultMetavoxelRendererImplementation::getSplatHeightScaleLocation(), 1.0f / _heightSize); DefaultMetavoxelRendererImplementation::getSplatHeightScaleLocation(), 1.0f / _heightSize);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getSplatTextureScaleLocation(), (float)_heightSize / innerSize); DefaultMetavoxelRendererImplementation::getSplatTextureScaleLocation(), (float)_heightSize / innerSize);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getSplatTextureOffsetLocation(),
_translation.x / _scale, _translation.z / _scale);
glBindTexture(GL_TEXTURE_2D, _textureTextureID); glBindTexture(GL_TEXTURE_2D, _textureTextureID);
const int TEXTURES_PER_SPLAT = 4; const int TEXTURES_PER_SPLAT = 4;
for (int i = 0; i < _textures.size(); i += TEXTURES_PER_SPLAT) { for (int i = 0; i < _textures.size(); i += TEXTURES_PER_SPLAT) {
QVector4D scalesS, scalesT;
for (int j = 0; j < SPLAT_COUNT; j++) { for (int j = 0; j < SPLAT_COUNT; j++) {
glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]); glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]);
int index = i + j; int index = i + j;
if (index < _networkTextures.size()) { if (index < _networkTextures.size()) {
const NetworkTexturePointer& texture = _networkTextures.at(index); const NetworkTexturePointer& texture = _networkTextures.at(index);
glBindTexture(GL_TEXTURE_2D, texture ? texture->getID() : 0); if (texture) {
HeightfieldTexture* heightfieldTexture = static_cast<HeightfieldTexture*>(_textures.at(index).data());
scalesS[j] = _scale / heightfieldTexture->getScaleS();
scalesT[j] = _scale / heightfieldTexture->getScaleT();
glBindTexture(GL_TEXTURE_2D, texture->getID());
} else {
glBindTexture(GL_TEXTURE_2D, 0);
}
} else { } else {
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
} }
} }
const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getSplatTextureScalesSLocation(), scalesS);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getSplatTextureScalesTLocation(), scalesT);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getSplatTextureValueMinimaLocation(), DefaultMetavoxelRendererImplementation::getSplatTextureValueMinimaLocation(),
(i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
@ -1050,6 +1066,9 @@ void DefaultMetavoxelRendererImplementation::init() {
_splatHeightfieldProgram.setUniformValueArray("diffuseMaps", SPLAT_TEXTURE_UNITS, SPLAT_COUNT); _splatHeightfieldProgram.setUniformValueArray("diffuseMaps", SPLAT_TEXTURE_UNITS, SPLAT_COUNT);
_splatHeightScaleLocation = _splatHeightfieldProgram.uniformLocation("heightScale"); _splatHeightScaleLocation = _splatHeightfieldProgram.uniformLocation("heightScale");
_splatTextureScaleLocation = _splatHeightfieldProgram.uniformLocation("textureScale"); _splatTextureScaleLocation = _splatHeightfieldProgram.uniformLocation("textureScale");
_splatTextureOffsetLocation = _splatHeightfieldProgram.uniformLocation("splatTextureOffset");
_splatTextureScalesSLocation = _splatHeightfieldProgram.uniformLocation("splatTextureScalesS");
_splatTextureScalesTLocation = _splatHeightfieldProgram.uniformLocation("splatTextureScalesT");
_splatTextureValueMinimaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMinima"); _splatTextureValueMinimaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMinima");
_splatTextureValueMaximaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMaxima"); _splatTextureValueMaximaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMaxima");
_splatHeightfieldProgram.release(); _splatHeightfieldProgram.release();
@ -1695,6 +1714,9 @@ int DefaultMetavoxelRendererImplementation::_baseColorScaleLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_splatHeightfieldProgram; ProgramObject DefaultMetavoxelRendererImplementation::_splatHeightfieldProgram;
int DefaultMetavoxelRendererImplementation::_splatHeightScaleLocation; int DefaultMetavoxelRendererImplementation::_splatHeightScaleLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureScaleLocation; int DefaultMetavoxelRendererImplementation::_splatTextureScaleLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureOffsetLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureScalesSLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureScalesTLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureValueMinimaLocation; int DefaultMetavoxelRendererImplementation::_splatTextureValueMinimaLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureValueMaximaLocation; int DefaultMetavoxelRendererImplementation::_splatTextureValueMaximaLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_lightHeightfieldProgram; ProgramObject DefaultMetavoxelRendererImplementation::_lightHeightfieldProgram;

View file

@ -252,6 +252,9 @@ public:
static ProgramObject& getSplatHeightfieldProgram() { return _splatHeightfieldProgram; } static ProgramObject& getSplatHeightfieldProgram() { return _splatHeightfieldProgram; }
static int getSplatHeightScaleLocation() { return _splatHeightScaleLocation; } static int getSplatHeightScaleLocation() { return _splatHeightScaleLocation; }
static int getSplatTextureScaleLocation() { return _splatTextureScaleLocation; } static int getSplatTextureScaleLocation() { return _splatTextureScaleLocation; }
static int getSplatTextureOffsetLocation() { return _splatTextureOffsetLocation; }
static int getSplatTextureScalesSLocation() { return _splatTextureScalesSLocation; }
static int getSplatTextureScalesTLocation() { return _splatTextureScalesTLocation; }
static int getSplatTextureValueMinimaLocation() { return _splatTextureValueMinimaLocation; } static int getSplatTextureValueMinimaLocation() { return _splatTextureValueMinimaLocation; }
static int getSplatTextureValueMaximaLocation() { return _splatTextureValueMaximaLocation; } static int getSplatTextureValueMaximaLocation() { return _splatTextureValueMaximaLocation; }
@ -297,6 +300,9 @@ private:
static ProgramObject _splatHeightfieldProgram; static ProgramObject _splatHeightfieldProgram;
static int _splatHeightScaleLocation; static int _splatHeightScaleLocation;
static int _splatTextureScaleLocation; static int _splatTextureScaleLocation;
static int _splatTextureOffsetLocation;
static int _splatTextureScalesSLocation;
static int _splatTextureScalesTLocation;
static int _splatTextureValueMinimaLocation; static int _splatTextureValueMinimaLocation;
static int _splatTextureValueMaximaLocation; static int _splatTextureValueMaximaLocation;

View file

@ -320,6 +320,7 @@ Texture::~Texture() {
NetworkTexture::NetworkTexture(const QUrl& url, TextureType type, const QByteArray& content) : NetworkTexture::NetworkTexture(const QUrl& url, TextureType type, const QByteArray& content) :
Resource(url, !content.isEmpty()), Resource(url, !content.isEmpty()),
_type(type),
_translucent(false) { _translucent(false) {
if (!url.isValid()) { if (!url.isValid()) {
@ -474,7 +475,13 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0,
GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); GL_RGB, GL_UNSIGNED_BYTE, image.constBits());
} }
if (_type == SPLAT_TEXTURE) {
// generate mipmaps for splat textures
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
} }

View file

@ -145,6 +145,7 @@ protected:
private: private:
TextureType _type;
bool _translucent; bool _translucent;
QColor _averageColor; QColor _averageColor;
}; };

View file

@ -1055,7 +1055,9 @@ void HeightfieldTextureData::read(Bitstream& in, int bytes) {
in >> _textures; in >> _textures;
} }
HeightfieldTexture::HeightfieldTexture() { HeightfieldTexture::HeightfieldTexture() :
_scaleS(1.0f),
_scaleT(1.0f) {
} }
HeightfieldAttribute::HeightfieldAttribute(const QString& name) : HeightfieldAttribute::HeightfieldAttribute(const QString& name) :

View file

@ -548,6 +548,8 @@ private:
class HeightfieldTexture : public SharedObject { class HeightfieldTexture : public SharedObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QUrl url MEMBER _url) Q_PROPERTY(QUrl url MEMBER _url)
Q_PROPERTY(float scaleS MEMBER _scaleS)
Q_PROPERTY(float scaleT MEMBER _scaleT)
public: public:
@ -555,9 +557,14 @@ public:
const QUrl& getURL() const { return _url; } const QUrl& getURL() const { return _url; }
float getScaleS() const { return _scaleS; }
float getScaleT() const { return _scaleT; }
private: private:
QUrl _url; QUrl _url;
float _scaleS;
float _scaleT;
}; };
/// An attribute that stores heightfield data. /// An attribute that stores heightfield data.

View file

@ -81,7 +81,7 @@ PacketVersion versionForPacketType(PacketType type) {
case PacketTypeAudioStreamStats: case PacketTypeAudioStreamStats:
return 1; return 1;
case PacketTypeMetavoxelData: case PacketTypeMetavoxelData:
return 2; return 3;
default: default:
return 0; return 0;
} }