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
//
// the number of splats per pass
const int SPLAT_COUNT = 4;
// the splat textures
@ -22,7 +23,7 @@ varying vec4 alphaValues;
void main(void) {
// blend the splat textures
gl_FragColor = gl_Color * (texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x +
texture2D(diffuseMaps[1], gl_TexCoord[0].st) * alphaValues.y +
texture2D(diffuseMaps[2], gl_TexCoord[0].st) * alphaValues.z +
texture2D(diffuseMaps[3], gl_TexCoord[0].st) * alphaValues.w);
texture2D(diffuseMaps[1], gl_TexCoord[1].st) * alphaValues.y +
texture2D(diffuseMaps[2], gl_TexCoord[2].st) * alphaValues.z +
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
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
uniform vec4 textureValueMinima;
@ -35,16 +44,21 @@ varying vec4 alphaValues;
void main(void) {
// add the height to the position
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
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0 - step(height, 0.0));
// 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
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);
alphaValues = step(textureValueMinima, valueVector) * step(valueVector, textureValueMaxima);
}

View file

@ -822,22 +822,38 @@ void HeightfieldBuffer::render(bool cursor) {
DefaultMetavoxelRendererImplementation::getSplatHeightScaleLocation(), 1.0f / _heightSize);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getSplatTextureScaleLocation(), (float)_heightSize / innerSize);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
DefaultMetavoxelRendererImplementation::getSplatTextureOffsetLocation(),
_translation.x / _scale, _translation.z / _scale);
glBindTexture(GL_TEXTURE_2D, _textureTextureID);
const int TEXTURES_PER_SPLAT = 4;
for (int i = 0; i < _textures.size(); i += TEXTURES_PER_SPLAT) {
QVector4D scalesS, scalesT;
for (int j = 0; j < SPLAT_COUNT; j++) {
glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]);
int index = i + j;
if (index < _networkTextures.size()) {
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 {
glBindTexture(GL_TEXTURE_2D, 0);
}
}
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::getSplatTextureValueMinimaLocation(),
(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);
_splatHeightScaleLocation = _splatHeightfieldProgram.uniformLocation("heightScale");
_splatTextureScaleLocation = _splatHeightfieldProgram.uniformLocation("textureScale");
_splatTextureOffsetLocation = _splatHeightfieldProgram.uniformLocation("splatTextureOffset");
_splatTextureScalesSLocation = _splatHeightfieldProgram.uniformLocation("splatTextureScalesS");
_splatTextureScalesTLocation = _splatHeightfieldProgram.uniformLocation("splatTextureScalesT");
_splatTextureValueMinimaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMinima");
_splatTextureValueMaximaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMaxima");
_splatHeightfieldProgram.release();
@ -1695,6 +1714,9 @@ int DefaultMetavoxelRendererImplementation::_baseColorScaleLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_splatHeightfieldProgram;
int DefaultMetavoxelRendererImplementation::_splatHeightScaleLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureScaleLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureOffsetLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureScalesSLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureScalesTLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureValueMinimaLocation;
int DefaultMetavoxelRendererImplementation::_splatTextureValueMaximaLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_lightHeightfieldProgram;

View file

@ -252,6 +252,9 @@ public:
static ProgramObject& getSplatHeightfieldProgram() { return _splatHeightfieldProgram; }
static int getSplatHeightScaleLocation() { return _splatHeightScaleLocation; }
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 getSplatTextureValueMaximaLocation() { return _splatTextureValueMaximaLocation; }
@ -297,6 +300,9 @@ private:
static ProgramObject _splatHeightfieldProgram;
static int _splatHeightScaleLocation;
static int _splatTextureScaleLocation;
static int _splatTextureOffsetLocation;
static int _splatTextureScalesSLocation;
static int _splatTextureScalesTLocation;
static int _splatTextureValueMinimaLocation;
static int _splatTextureValueMaximaLocation;

View file

@ -320,6 +320,7 @@ Texture::~Texture() {
NetworkTexture::NetworkTexture(const QUrl& url, TextureType type, const QByteArray& content) :
Resource(url, !content.isEmpty()),
_type(type),
_translucent(false) {
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,
GL_RGB, GL_UNSIGNED_BYTE, image.constBits());
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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);
}
glBindTexture(GL_TEXTURE_2D, 0);
}

View file

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

View file

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

View file

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

View file

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