Merge pull request #1170 from ZappoMan/point_shader

first cut a variable point size point rendering
This commit is contained in:
Philip Rosedale 2013-11-01 17:02:28 -07:00
commit 79fb92f195
6 changed files with 193 additions and 3 deletions

View file

@ -0,0 +1,49 @@
#version 120
attribute float voxelSizeIn;
varying float voxelSize;
uniform float viewportWidth;
uniform float viewportHeight;
void main(void) {
gl_FrontColor = gl_Color;
vec4 cornerOriginal = gl_Vertex;
vec4 corner = gl_ModelViewProjectionMatrix * gl_Vertex;
// I'm currently using the distance between the near bottom left corner and the far top right corner. That's not
// ideal for all possible angles of viewing of the voxel. I really should be using a lookup table to determine which
// corners to use.
//
// The effect with the current approach is that some "projections" are smaller than they should be, and we get a
// thinning effect. However, this may not matter when we actually switch to using cubes and points in concert.
//
vec4 farCornerVertex = gl_Vertex;
farCornerVertex += vec4(voxelSizeIn, voxelSizeIn, voxelSizeIn, 0.0);
vec4 farCorner = gl_ModelViewProjectionMatrix * farCornerVertex;
// math! If the w result is negative then the point is behind the viewer
vec2 cornerOnScreen = vec2(corner.x / corner.w, corner.y / corner.w);
if (corner.w < 0) {
cornerOnScreen.x = -cornerOnScreen.x;
cornerOnScreen.y = -cornerOnScreen.y;
}
vec2 farCornerOnScreen = vec2(farCorner.x / farCorner.w, farCorner.y / farCorner.w);
if (farCorner.w < 0) {
farCornerOnScreen.x = -farCornerOnScreen.x;
farCornerOnScreen.y = -farCornerOnScreen.y;
}
float voxelScreenWidth = abs(farCornerOnScreen.x - cornerOnScreen.x) * viewportWidth / 2.0;
float voxelScreenHeight = abs(farCornerOnScreen.y - cornerOnScreen.y) * viewportHeight / 2.0;
float voxelScreenLength = sqrt(voxelScreenHeight * voxelScreenHeight + voxelScreenWidth * voxelScreenWidth);
vec4 centerVertex = gl_Vertex;
float halfSizeIn = voxelSizeIn / 2;
centerVertex += vec4(halfSizeIn, halfSizeIn, halfSizeIn, 0.0);
vec4 center = gl_ModelViewProjectionMatrix * centerVertex;
gl_Position = center;
gl_PointSize = voxelScreenLength;
}

View file

@ -1665,6 +1665,7 @@ void Application::init() {
_glowEffect.init();
_ambientOcclusionEffect.init();
_voxelShader.init();
_pointShader.init();
_handControl.setScreenDimensions(_glWidget->width(), _glWidget->height());

View file

@ -55,6 +55,7 @@
#include "renderer/GeometryCache.h"
#include "renderer/GlowEffect.h"
#include "renderer/VoxelShader.h"
#include "renderer/PointShader.h"
#include "renderer/TextureCache.h"
#include "ui/BandwidthDialog.h"
#include "ui/ChatEntry.h"
@ -162,6 +163,9 @@ public:
virtual void domainChanged(QString domain);
VoxelShader& getVoxelShader() { return _voxelShader; }
PointShader& getPointShader() { return _pointShader; }
glm::vec2 getViewportDimensions() const{ return glm::vec2(_glWidget->width(),_glWidget->height()); }
public slots:
void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data);
@ -383,6 +387,7 @@ private:
GlowEffect _glowEffect;
AmbientOcclusionEffect _ambientOcclusionEffect;
VoxelShader _voxelShader;
PointShader _pointShader;
#ifndef _WIN32
Audio _audio;

View file

@ -1257,13 +1257,27 @@ void VoxelSystem::render(bool texture) {
if (!_voxelsAsPoints) {
Application::getInstance()->getVoxelShader().begin();
attributeLocation = Application::getInstance()->getVoxelShader().attributeLocation("voxelSizeIn");
glEnableVertexAttribArray(attributeLocation);
glVertexAttribPointer(attributeLocation, 1, GL_FLOAT, false, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(3*sizeof(float)));
} else {
const float POINT_SIZE = 4.0;
glPointSize(POINT_SIZE);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
glm::vec2 viewDimensions = Application::getInstance()->getViewportDimensions();
float viewportWidth = viewDimensions.x;
float viewportHeight = viewDimensions.y;
Application::getInstance()->getPointShader().begin();
int uniformLocation = Application::getInstance()->getPointShader().uniformLocation("viewportWidth");
Application::getInstance()->getPointShader().setUniformValue(uniformLocation, viewportWidth);
uniformLocation = Application::getInstance()->getPointShader().uniformLocation("viewportHeight");
Application::getInstance()->getPointShader().setUniformValue(uniformLocation, viewportHeight);
attributeLocation = Application::getInstance()->getVoxelShader().attributeLocation("voxelSizeIn");
glEnableVertexAttribArray(attributeLocation);
glVertexAttribPointer(attributeLocation, 1, GL_FLOAT, false, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(3*sizeof(float)));
}
@ -1287,6 +1301,10 @@ void VoxelSystem::render(bool texture) {
if (!_voxelsAsPoints) {
Application::getInstance()->getVoxelShader().end();
glDisableVertexAttribArray(attributeLocation);
} else {
Application::getInstance()->getPointShader().end();
glDisableVertexAttribArray(attributeLocation);
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
}
} else {
PerformanceWarning warn(showWarnings, "render().. TRIANGLES...");

View file

@ -0,0 +1,73 @@
//
// PointShader.cpp
// interface
//
// Created by Brad Hefta-Gaub on 10/30/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <QOpenGLFramebufferObject>
#include "Application.h"
#include "PointShader.h"
#include "ProgramObject.h"
#include "RenderUtil.h"
PointShader::PointShader()
: _initialized(false)
{
_program = NULL;
}
PointShader::~PointShader() {
if (_initialized) {
delete _program;
}
}
ProgramObject* PointShader::createPointShaderProgram(const QString& name) {
ProgramObject* program = new ProgramObject();
program->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/" + name + ".vert" );
program->link();
return program;
}
void PointShader::init() {
if (_initialized) {
qDebug("[ERROR] PointShader is already initialized.\n");
return;
}
switchToResourcesParentIfRequired();
_program = createPointShaderProgram("point_size");
_initialized = true;
}
void PointShader::begin() {
_program->bind();
}
void PointShader::end() {
_program->release();
}
int PointShader::attributeLocation(const char* name) const {
if (_program) {
return _program->attributeLocation(name);
} else {
return -1;
}
}
int PointShader::uniformLocation(const char* name) const {
if (_program) {
return _program->uniformLocation(name);
} else {
return -1;
}
}
void PointShader::setUniformValue(int attributeLocation, float value) {
_program->setUniformValue(attributeLocation, value);
}

View file

@ -0,0 +1,44 @@
//
// PointShader.h
// interface
//
// Created by Brad Hefta-Gaub on 10/30/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__PointShader__
#define __interface__PointShader__
#include <QObject>
class ProgramObject;
/// A shader program that draws voxels as points with variable sizes
class PointShader : public QObject {
Q_OBJECT
public:
PointShader();
~PointShader();
void init();
/// Starts using the voxel point shader program.
void begin();
/// Stops using the voxel point shader program.
void end();
/// Gets access to attributes from the shader program
int attributeLocation(const char* name) const;
int uniformLocation(const char* name) const;
void setUniformValue(int attributeLocation, float value);
static ProgramObject* createPointShaderProgram(const QString& name);
private:
bool _initialized;
ProgramObject* _program;
};
#endif /* defined(__interface__PointShader__) */