mirror of
https://github.com/overte-org/overte.git
synced 2025-04-16 05:48:39 +02:00
Glow line replacement without geometry shader
This commit is contained in:
parent
e9563ef9af
commit
3074be7ad0
8 changed files with 121 additions and 187 deletions
|
@ -39,11 +39,11 @@ bool DebugHmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
|||
_uiModelTransform = DependencyManager::get<CompositorHelper>()->getModelTransform();
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
|
||||
_handPoses[0] = glm::translate(mat4(), vec3(-0.3f, 0.0f, 0.0f));
|
||||
_handPoses[0] = glm::translate(mat4(), vec3(0.3f * cosf(secTimestampNow() * 3.0f), -0.3f * sinf(secTimestampNow() * 5.0f), 0.0f));
|
||||
_handLasers[0].color = vec4(1, 0, 0, 1);
|
||||
_handLasers[0].mode = HandLaserMode::Overlay;
|
||||
|
||||
_handPoses[1] = glm::translate(mat4(), vec3(0.3f, 0.0f, 0.0f));
|
||||
_handPoses[1] = glm::translate(mat4(), vec3(0.3f * sinf(secTimestampNow() * 3.0f), -0.3f * cosf(secTimestampNow() * 5.0f), 0.0f));
|
||||
_handLasers[1].color = vec4(0, 1, 1, 1);
|
||||
_handLasers[1].mode = HandLaserMode::Overlay;
|
||||
});
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <CursorManager.h>
|
||||
#include <gl/GLWidget.h>
|
||||
#include <shared/NsightHelpers.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
#include <gpu/gl/GLBackend.h>
|
||||
|
@ -32,6 +31,9 @@
|
|||
|
||||
#include "../Logging.h"
|
||||
#include "../CompositorHelper.h"
|
||||
#include <../render-utils/shaders/render-utils/glowLine_vert.h>
|
||||
#include <../render-utils/shaders/render-utils/glowLine_frag.h>
|
||||
|
||||
|
||||
static const QString MONO_PREVIEW = "Mono Preview";
|
||||
static const QString DISABLE_PREVIEW = "Disable Preview";
|
||||
|
@ -47,6 +49,14 @@ static const size_t NUMBER_OF_HANDS = 2;
|
|||
//#define LIVE_SHADER_RELOAD 1
|
||||
extern glm::vec3 getPoint(float yaw, float pitch);
|
||||
|
||||
struct HandLaserData {
|
||||
vec4 p1;
|
||||
vec4 p2;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
static const uint32_t HAND_LASER_UNIFORM_SLOT = 1;
|
||||
|
||||
static QString readFile(const QString& filename) {
|
||||
QFile file(filename);
|
||||
file.open(QFile::Text | QFile::ReadOnly);
|
||||
|
@ -112,11 +122,25 @@ void HmdDisplayPlugin::internalDeactivate() {
|
|||
void HmdDisplayPlugin::customizeContext() {
|
||||
Parent::customizeContext();
|
||||
_overlayRenderer.build();
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
for (size_t i = 0; i < _geometryIds.size(); ++i) {
|
||||
_geometryIds[i] = geometryCache->allocateID();
|
||||
}
|
||||
_extraLaserID = geometryCache->allocateID();
|
||||
|
||||
{
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
auto VS = gpu::Shader::createVertex(std::string(glowLine_vert));
|
||||
auto PS = gpu::Shader::createPixel(std::string(glowLine_frag));
|
||||
auto program = gpu::Shader::createProgram(VS, PS);
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("lineData"), HAND_LASER_UNIFORM_SLOT));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
_glowLinePipeline = gpu::Pipeline::create(program, state);
|
||||
_handLaserUniforms = std::array<gpu::BufferPointer, 2>{ { std::make_shared<gpu::Buffer>(), std::make_shared<gpu::Buffer>() } };
|
||||
_extraLaserUniforms = std::make_shared<gpu::Buffer>();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::uncustomizeContext() {
|
||||
|
@ -131,12 +155,10 @@ void HmdDisplayPlugin::uncustomizeContext() {
|
|||
});
|
||||
_overlayRenderer = OverlayRenderer();
|
||||
_previewTexture.reset();
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
for (size_t i = 0; i < _geometryIds.size(); ++i) {
|
||||
geometryCache->releaseID(_geometryIds[i]);
|
||||
}
|
||||
geometryCache->releaseID(_extraLaserID);
|
||||
_handLaserUniforms[0].reset();
|
||||
_handLaserUniforms[1].reset();
|
||||
_extraLaserUniforms.reset();
|
||||
_glowLinePipeline.reset();
|
||||
Parent::uncustomizeContext();
|
||||
}
|
||||
|
||||
|
@ -683,11 +705,15 @@ void HmdDisplayPlugin::compositeExtra() {
|
|||
return;
|
||||
}
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
render([&](gpu::Batch& batch) {
|
||||
batch.setFramebuffer(_compositeFramebuffer);
|
||||
batch.setModelTransform(Transform());
|
||||
batch.setViewportTransform(ivec4(uvec2(0), _renderTargetSize));
|
||||
batch.setViewTransform(_currentPresentFrameInfo.presentPose, false);
|
||||
// Compile the shaders
|
||||
batch.setPipeline(_glowLinePipeline);
|
||||
|
||||
|
||||
bilateral::for_each_side([&](bilateral::Side side){
|
||||
auto index = bilateral::index(side);
|
||||
if (_presentHandPoses[index] == IDENTITY_MATRIX) {
|
||||
|
@ -696,13 +722,20 @@ void HmdDisplayPlugin::compositeExtra() {
|
|||
const auto& laser = _presentHandLasers[index];
|
||||
if (laser.valid()) {
|
||||
const auto& points = _presentHandLaserPoints[index];
|
||||
geometryCache->renderGlowLine(batch, points.first, points.second, laser.color, _geometryIds[index]);
|
||||
_handLaserUniforms[index]->resize(sizeof(HandLaserData));
|
||||
_handLaserUniforms[index]->setSubData(0, HandLaserData { vec4(points.first, 1.0f), vec4(points.second, 1.0f), _handLasers[index].color });
|
||||
batch.setUniformBuffer(HAND_LASER_UNIFORM_SLOT, _handLaserUniforms[index]);
|
||||
qDebug() << "Render line " << index;
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4, 0);
|
||||
}
|
||||
});
|
||||
|
||||
if (_presentExtraLaser.valid()) {
|
||||
const auto& points = _presentExtraLaserPoints;
|
||||
geometryCache->renderGlowLine(batch, points.first, points.second, _presentExtraLaser.color, _extraLaserID);
|
||||
_extraLaserUniforms->resize(sizeof(HandLaserData));
|
||||
_extraLaserUniforms->setSubData(0, HandLaserData { vec4(points.first, 1.0f), vec4(points.second, 1.0f), _presentExtraLaser.color });
|
||||
batch.setUniformBuffer(HAND_LASER_UNIFORM_SLOT, _extraLaserUniforms);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -80,8 +80,6 @@ protected:
|
|||
|
||||
Transform _presentUiModelTransform;
|
||||
std::array<HandLaserInfo, 2> _presentHandLasers;
|
||||
std::array<int, 2> _geometryIds;
|
||||
int _extraLaserID;
|
||||
std::array<mat4, 2> _presentHandPoses;
|
||||
std::array<std::pair<vec3, vec3>, 2> _presentHandLaserPoints;
|
||||
|
||||
|
@ -120,6 +118,9 @@ private:
|
|||
bool _disablePreviewItemAdded { false };
|
||||
bool _monoPreview { true };
|
||||
bool _clearPreviewFlag { false };
|
||||
std::array<gpu::BufferPointer, 2> _handLaserUniforms;
|
||||
gpu::BufferPointer _extraLaserUniforms;
|
||||
gpu::PipelinePointer _glowLinePipeline;
|
||||
gpu::TexturePointer _previewTexture;
|
||||
glm::vec2 _lastWindowSize;
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "simple_opaque_web_browser_frag.h"
|
||||
#include "simple_transparent_web_browser_frag.h"
|
||||
#include "glowLine_vert.h"
|
||||
#include "glowLine_geom.h"
|
||||
#include "glowLine_frag.h"
|
||||
|
||||
#include "grid_frag.h"
|
||||
|
@ -1405,6 +1404,7 @@ GeometryCache::BatchItemDetails::~BatchItemDetails() {
|
|||
|
||||
void GeometryCache::BatchItemDetails::clear() {
|
||||
isCreated = false;
|
||||
uniformBuffer.reset();
|
||||
verticesBuffer.reset();
|
||||
colorBuffer.reset();
|
||||
streamFormat.reset();
|
||||
|
@ -1593,8 +1593,6 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const
|
|||
glowIntensity = 0.0f;
|
||||
#endif
|
||||
|
||||
glowIntensity = 0.0f;
|
||||
|
||||
if (glowIntensity <= 0) {
|
||||
bindSimpleProgram(batch, false, false, false, true, false);
|
||||
renderLine(batch, p1, p2, color, id);
|
||||
|
@ -1602,20 +1600,20 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const
|
|||
}
|
||||
|
||||
// Compile the shaders
|
||||
static const uint32_t LINE_DATA_SLOT = 1;
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
auto VS = gpu::Shader::createVertex(std::string(glowLine_vert));
|
||||
auto GS = gpu::Shader::createGeometry(std::string(glowLine_geom));
|
||||
auto PS = gpu::Shader::createPixel(std::string(glowLine_frag));
|
||||
auto program = gpu::Shader::createProgram(VS, GS, PS);
|
||||
auto program = gpu::Shader::createProgram(VS, PS);
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("lineData"), LINE_DATA_SLOT));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
_glowLinePipeline = gpu::Pipeline::create(program, state);
|
||||
});
|
||||
|
@ -1626,11 +1624,6 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const
|
|||
bool registered = (id != UNKNOWN_ID);
|
||||
BatchItemDetails& details = _registeredLine3DVBOs[id];
|
||||
|
||||
int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
||||
((int(color.y * 255.0f) & 0xFF) << 8) |
|
||||
((int(color.z * 255.0f) & 0xFF) << 16) |
|
||||
((int(color.w * 255.0f) & 0xFF) << 24);
|
||||
|
||||
// if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed
|
||||
if (registered && details.isCreated) {
|
||||
Vec3Pair& lastKey = _lastRegisteredLine3D[id];
|
||||
|
@ -1640,47 +1633,25 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const
|
|||
}
|
||||
}
|
||||
|
||||
const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals
|
||||
const int NUM_POS_COORDS = 3;
|
||||
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||
const int vertices = 2;
|
||||
const int NUM_VERTICES = 4;
|
||||
if (!details.isCreated) {
|
||||
details.isCreated = true;
|
||||
details.vertices = vertices;
|
||||
details.vertexSize = FLOATS_PER_VERTEX;
|
||||
details.uniformBuffer = std::make_shared<gpu::Buffer>();
|
||||
|
||||
auto verticesBuffer = std::make_shared<gpu::Buffer>();
|
||||
auto colorBuffer = std::make_shared<gpu::Buffer>();
|
||||
auto streamFormat = std::make_shared<gpu::Stream::Format>();
|
||||
auto stream = std::make_shared<gpu::BufferStream>();
|
||||
struct LineData {
|
||||
vec4 p1;
|
||||
vec4 p2;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
details.verticesBuffer = verticesBuffer;
|
||||
details.colorBuffer = colorBuffer;
|
||||
details.streamFormat = streamFormat;
|
||||
details.stream = stream;
|
||||
|
||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||
|
||||
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
||||
|
||||
const glm::vec3 NORMAL(1.0f, 0.0f, 0.0f);
|
||||
float vertexBuffer[vertices * FLOATS_PER_VERTEX] = {
|
||||
p1.x, p1.y, p1.z, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||
p2.x, p2.y, p2.z, NORMAL.x, NORMAL.y, NORMAL.z };
|
||||
|
||||
const int NUM_COLOR_SCALARS = 2;
|
||||
int colors[NUM_COLOR_SCALARS] = { compactColor, compactColor };
|
||||
details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer);
|
||||
details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);
|
||||
LineData lineData { vec4(p1, 1.0f), vec4(p2, 1.0f), color };
|
||||
details.uniformBuffer->resize(sizeof(LineData));
|
||||
details.uniformBuffer->setSubData(0, lineData);
|
||||
}
|
||||
|
||||
// this is what it takes to render a quad
|
||||
batch.setInputFormat(details.streamFormat);
|
||||
batch.setInputStream(0, *details.stream);
|
||||
batch.draw(gpu::LINES, 2, 0);
|
||||
// The shader requires no vertices, only uniforms.
|
||||
batch.setUniformBuffer(LINE_DATA_SLOT, details.uniformBuffer);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, NUM_VERTICES, 0);
|
||||
}
|
||||
|
||||
void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
|
||||
|
|
|
@ -369,6 +369,7 @@ private:
|
|||
static int population;
|
||||
gpu::BufferPointer verticesBuffer;
|
||||
gpu::BufferPointer colorBuffer;
|
||||
gpu::BufferPointer uniformBuffer;
|
||||
gpu::Stream::FormatPointer streamFormat;
|
||||
gpu::BufferStreamPointer stream;
|
||||
|
||||
|
|
|
@ -10,26 +10,24 @@
|
|||
//
|
||||
|
||||
layout(location = 0) in vec4 inColor;
|
||||
layout(location = 1) in vec3 inLineDistance;
|
||||
|
||||
out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
vec2 d = inLineDistance.xy;
|
||||
d.y = abs(d.y);
|
||||
d.x = abs(d.x);
|
||||
if (d.x > 1.0) {
|
||||
d.x = (d.x - 1.0) / 0.02;
|
||||
} else {
|
||||
d.x = 0.0;
|
||||
}
|
||||
float alpha = 1.0 - length(d);
|
||||
if (alpha <= 0.0) {
|
||||
discard;
|
||||
}
|
||||
alpha = pow(alpha, 10.0);
|
||||
if (alpha < 0.05) {
|
||||
// The incoming value actually ranges from -1 to 1, so modify it
|
||||
// so that it goes from 0 -> 1 -> 0 with the solid alpha being at
|
||||
// the center of the line
|
||||
float alpha = 1.0 - abs(inColor.a);
|
||||
|
||||
// Convert from a linear alpha curve to a sharp peaked one
|
||||
alpha = pow(alpha, 10);
|
||||
|
||||
// Drop everything where the curve falls off to nearly nothing
|
||||
if (alpha <= 0.05) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Emit the color
|
||||
_fragColor = vec4(inColor.rgb, alpha);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2016/07/05
|
||||
// Copyright 2013-2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#extension GL_EXT_geometry_shader4 : enable
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardCameraTransform()$>
|
||||
|
||||
layout(location = 0) in vec4 inColor[];
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
layout(location = 1) out vec3 outLineDistance;
|
||||
|
||||
layout(lines) in;
|
||||
layout(triangle_strip, max_vertices = 24) out;
|
||||
|
||||
vec3 ndcToEyeSpace(in vec4 v) {
|
||||
TransformCamera cam = getTransformCamera();
|
||||
vec4 u = cam._projectionInverse * v;
|
||||
return u.xyz / u.w;
|
||||
}
|
||||
|
||||
vec2 toScreenSpace(in vec4 v)
|
||||
{
|
||||
TransformCamera cam = getTransformCamera();
|
||||
vec4 u = cam._projection * cam._view * v;
|
||||
return u.xy / u.w;
|
||||
}
|
||||
|
||||
vec3[2] getOrthogonals(in vec3 n, float scale) {
|
||||
float yDot = abs(dot(n, vec3(0, 1, 0)));
|
||||
|
||||
vec3 result[2];
|
||||
if (yDot < 0.9) {
|
||||
result[0] = normalize(cross(n, vec3(0, 1, 0)));
|
||||
} else {
|
||||
result[0] = normalize(cross(n, vec3(1, 0, 0)));
|
||||
}
|
||||
// The cross of result[0] and n is orthogonal to both, which are orthogonal to each other
|
||||
result[1] = cross(result[0], n);
|
||||
result[0] *= scale;
|
||||
result[1] *= scale;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
vec2 orthogonal(vec2 v) {
|
||||
vec2 result = v.yx;
|
||||
result.y *= -1.0;
|
||||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 endpoints[2];
|
||||
vec3 eyeSpace[2];
|
||||
TransformCamera cam = getTransformCamera();
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
eyeSpace[i] = ndcToEyeSpace(gl_PositionIn[i]);
|
||||
endpoints[i] = gl_PositionIn[i].xy / gl_PositionIn[i].w;
|
||||
}
|
||||
vec2 lineNormal = normalize(endpoints[1] - endpoints[0]);
|
||||
vec2 lineOrthogonal = orthogonal(lineNormal);
|
||||
lineNormal *= 0.02;
|
||||
lineOrthogonal *= 0.02;
|
||||
|
||||
gl_Position = gl_PositionIn[0];
|
||||
gl_Position.xy -= lineOrthogonal;
|
||||
outColor = inColor[0];
|
||||
outLineDistance = vec3(-1.02, -1, gl_Position.z);
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_PositionIn[0];
|
||||
gl_Position.xy += lineOrthogonal;
|
||||
outColor = inColor[0];
|
||||
outLineDistance = vec3(-1.02, 1, gl_Position.z);
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_PositionIn[1];
|
||||
gl_Position.xy -= lineOrthogonal;
|
||||
outColor = inColor[1];
|
||||
outLineDistance = vec3(1.02, -1, gl_Position.z);
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = gl_PositionIn[1];
|
||||
gl_Position.xy += lineOrthogonal;
|
||||
outColor = inColor[1];
|
||||
outLineDistance = vec3(1.02, 1, gl_Position.z);
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -9,18 +9,50 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
layout(std140) uniform lineData {
|
||||
vec4 p1;
|
||||
vec4 p2;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
layout(location = 0) out vec4 _color;
|
||||
|
||||
void main(void) {
|
||||
_color = inColor;
|
||||
_color = color;
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
|
||||
vec4 p1eye, p2eye;
|
||||
<$transformModelToEyePos(cam, obj, p1, p1eye)$>
|
||||
<$transformModelToEyePos(cam, obj, p2, p2eye)$>
|
||||
p1eye /= p1eye.w;
|
||||
p2eye /= p2eye.w;
|
||||
|
||||
// Find the line direction
|
||||
vec3 v1 = normalize(p1eye.xyz - p2eye.xyz);
|
||||
// Find the vector from the eye to one of the points
|
||||
vec3 v2 = normalize(p1eye.xyz);
|
||||
// The orthogonal vector is the cross product of these two
|
||||
vec3 orthogonal = cross(v1, v2) * 0.02;
|
||||
|
||||
// Deteremine which end to emit based on the vertex id (even / odd)
|
||||
vec4 eye = (0 == gl_VertexID % 2) ? p1eye : p2eye;
|
||||
|
||||
// Add or subtract the orthogonal vector based on a different vertex ID
|
||||
// calculation
|
||||
if (gl_VertexID < 2) {
|
||||
// Use the alpha channel to store the distance from the center in 'quad space'
|
||||
_color.a = -1.0;
|
||||
eye.xyz -= orthogonal;
|
||||
} else {
|
||||
_color.a = 1.0;
|
||||
eye.xyz += orthogonal;
|
||||
}
|
||||
|
||||
// Finally, put the eyespace vertex into clip space
|
||||
<$transformEyeToClipPos(cam, eye, gl_Position)$>
|
||||
}
|
Loading…
Reference in a new issue