Color matrices and many effect spheres

This commit is contained in:
JozsefA 2021-04-13 23:52:52 -07:00
parent db7913d91b
commit 7988fb69a7
12 changed files with 449 additions and 190 deletions

View file

@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.KineticRenderer;
@ -56,10 +57,6 @@ public class RenderHooksMixin {
ContraptionRenderDispatcher.renderLayer(type, viewProjection, camX, camY, camZ);
GL20.glUseProgram(0);
if (type == RenderType.getTranslucent()) {
Backend.effects.render(view);
}
}
@Inject(at = @At(value = "INVOKE", target = "net.minecraft.client.renderer.WorldRenderer.updateChunks(J)V"), method = "render")
@ -76,6 +73,16 @@ public class RenderHooksMixin {
ContraptionRenderDispatcher.beginFrame(info, camX, camY, camZ);
}
@Inject(method = "render", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/client/shader/ShaderGroup;render(F)V"))
private void disableTransparencyShaderDepth(MatrixStack p_228426_1_, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, ActiveRenderInfo p_228426_6_, GameRenderer p_228426_7_, LightTexture p_228426_8_, Matrix4f p_228426_9_, CallbackInfo ci) {
GlStateManager.depthMask(false);
}
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/WorldRenderer;renderChunkDebugInfo(Lnet/minecraft/client/renderer/ActiveRenderInfo;)V"))
private void applyFilters(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, ActiveRenderInfo p_228426_6_, GameRenderer p_228426_7_, LightTexture p_228426_8_, Matrix4f p_228426_9_, CallbackInfo ci) {
Backend.effects.render(stack.peek().getModel());
}
@Inject(at = @At("TAIL"), method = "scheduleBlockRerenderIfNeeded")
private void checkUpdate(BlockPos pos, BlockState lastState, BlockState newState, CallbackInfo ci) {
CreateClient.kineticRenderer.get(world)

View file

@ -15,7 +15,7 @@ import com.simibubi.create.foundation.render.backend.core.BasicProgram;
import com.simibubi.create.foundation.render.backend.core.ModelAttributes;
import com.simibubi.create.foundation.render.backend.core.OrientedAttributes;
import com.simibubi.create.foundation.render.backend.core.TransformAttributes;
import com.simibubi.create.foundation.render.backend.effects.PostProcessingProgram;
import com.simibubi.create.foundation.render.backend.effects.SphereFilterProgram;
import com.simibubi.create.foundation.render.backend.gl.shader.FogSensitiveProgram;
import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec;
import com.simibubi.create.foundation.render.backend.gl.shader.ShaderConstants;
@ -28,12 +28,12 @@ public class AllProgramSpecs {
// noop, make sure the static field are loaded.
}
public static final ProgramSpec<PostProcessingProgram> CHROMATIC = register(ProgramSpec.builder("chromatic", new SingleProgram.SpecLoader<>(PostProcessingProgram::new))
public static final ProgramSpec<SphereFilterProgram> CHROMATIC = register(ProgramSpec.builder("chromatic", new SingleProgram.SpecLoader<>(SphereFilterProgram::new))
.addAttributes(ModelAttributes.class)
.addAttributes(BasicAttributes.class)
.addAttributes(TransformAttributes.class)
.setVert(Locations.SCREEN_QUAD)
.setFrag(Locations.CHROMATIC)
.setVert(Locations.EFFECT_VERT)
.setFrag(Locations.EFFECT_FRAG)
.createProgramSpec());
public static final ProgramSpec<BasicProgram> MODEL = register(ProgramSpec.builder("model", new FogSensitiveProgram.SpecLoader<>(BasicProgram::new))
@ -131,8 +131,8 @@ public class AllProgramSpecs {
public static class Locations {
public static final ResourceLocation SCREEN_QUAD = loc("screen_quad.vert");
public static final ResourceLocation CHROMATIC = loc("chromatic.frag");
public static final ResourceLocation EFFECT_VERT = loc("area_effect.vert");
public static final ResourceLocation EFFECT_FRAG = loc("area_effect.frag");
public static final ResourceLocation MODEL_FRAG = loc("model.frag");
public static final ResourceLocation MODEL_VERT = loc("model.vert");
public static final ResourceLocation ORIENTED = loc("oriented.vert");

View file

@ -0,0 +1,81 @@
package com.simibubi.create.foundation.render.backend.effects;
import com.simibubi.create.foundation.utility.AngleHelper;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Matrix4f;
public class ColorMatrices {
public static final float lumaR = 0.3086f;
public static final float lumaG = 0.6094f;
public static final float lumaB = 0.0820f;
public static Matrix4f grayscale() {
Matrix4f mat = new Matrix4f();
mat.a00 = mat.a01 = mat.a02 = lumaR;
mat.a10 = mat.a11 = mat.a12 = lumaG;
mat.a20 = mat.a21 = mat.a22 = lumaB;
mat.a33 = 1;
return mat;
}
public static Matrix4f saturate(float s) {
Matrix4f mat = new Matrix4f();
mat.a00 = (1.0f - s) * lumaR + s;
mat.a01 = (1.0f - s) * lumaR;
mat.a02 = (1.0f - s) * lumaR;
mat.a10 = (1.0f - s) * lumaG;
mat.a11 = (1.0f - s) * lumaG + s;
mat.a12 = (1.0f - s) * lumaG;
mat.a20 = (1.0f - s) * lumaB;
mat.a21 = (1.0f - s) * lumaB;
mat.a22 = (1.0f - s) * lumaB + s;
mat.a33 = 1;
return mat;
}
public static Matrix4f sepia(float amount) {
Matrix4f mat = new Matrix4f();
mat.a00 = (float) (0.393 + 0.607 * (1 - amount));
mat.a10 = (float) (0.769 - 0.769 * (1 - amount));
mat.a20 = (float) (0.189 - 0.189 * (1 - amount));
mat.a01 = (float) (0.349 - 0.349 * (1 - amount));
mat.a11 = (float) (0.686 + 0.314 * (1 - amount));
mat.a21 = (float) (0.168 - 0.168 * (1 - amount));
mat.a02 = (float) (0.272 - 0.272 * (1 - amount));
mat.a12 = (float) (0.534 - 0.534 * (1 - amount));
mat.a22 = (float) (0.131 + 0.869 * (1 - amount));
mat.a33 = 1;
return mat;
}
// https://stackoverflow.com/a/8510751
public static Matrix4f hueShift(float rot) {
Matrix4f mat = new Matrix4f();
mat.loadIdentity();
float cosA = MathHelper.cos(AngleHelper.rad(rot));
float sinA = MathHelper.sin(AngleHelper.rad(rot));
mat.a00 = (float) (cosA + (1.0 - cosA) / 3.0);
mat.a01 = (float) (1. / 3. * (1.0 - cosA) - MathHelper.sqrt(1. / 3.) * sinA);
mat.a02 = (float) (1. / 3. * (1.0 - cosA) + MathHelper.sqrt(1. / 3.) * sinA);
mat.a10 = (float) (1. / 3. * (1.0 - cosA) + MathHelper.sqrt(1. / 3.) * sinA);
mat.a11 = (float) (cosA + 1. / 3. * (1.0 - cosA));
mat.a12 = (float) (1. / 3. * (1.0 - cosA) - MathHelper.sqrt(1. / 3.) * sinA);
mat.a20 = (float) (1. / 3. * (1.0 - cosA) - MathHelper.sqrt(1. / 3.) * sinA);
mat.a21 = (float) (1. / 3. * (1.0 - cosA) + MathHelper.sqrt(1. / 3.) * sinA);
mat.a22 = (float) (cosA + 1. / 3. * (1.0 - cosA));
return mat;
}
}

View file

@ -26,7 +26,7 @@ public class EffectsHandler {
}
public static float getFarPlane() {
return Minecraft.getInstance().gameRenderer.getFarPlaneDistance();
return Minecraft.getInstance().gameRenderer.getFarPlaneDistance() * 4;
}
public static final float[] vertices = {
@ -75,6 +75,10 @@ public class EffectsHandler {
}
public void render(Matrix4f view) {
// if (true) {
// return;
// }
GL20.glEnable(GL20.GL_DEPTH_TEST);
GL20.glDepthRange(getNearPlane(), getFarPlane());
@ -87,8 +91,9 @@ public class EffectsHandler {
Framebuffer mainBuffer = Minecraft.getInstance().getFramebuffer();
GL30.glBindFramebuffer(FramebufferConstants.FRAME_BUFFER, framebuffer.framebufferObject);
GL30.glClear(GL30.GL_COLOR_BUFFER_BIT);
PostProcessingProgram program = Backend.getProgram(AllProgramSpecs.CHROMATIC);
SphereFilterProgram program = Backend.getProgram(AllProgramSpecs.CHROMATIC);
program.bind();
program.bindColorTexture(mainBuffer.getColorAttachment());
@ -104,15 +109,37 @@ public class EffectsHandler {
Matrix4f inverseView = view.copy();
inverseView.invert();
// Matrix4f inverseView = new Matrix4f();
// inverseView.loadIdentity();
program.bindInverseView(inverseView);
Vector3d pos = new Vector3d(286, 73, -149);
Vector3d pos1 = new Vector3d(330, 0, 110);
// Vector3d pos1 = new Vector3d(852, 79, -204);
// Vector3d pos2 = new Vector3d(858, 95, -260);
// Vector3d pos3 = new Vector3d(906, 84, -207);
Vector3d cameraPos = gameRenderer.getActiveRenderInfo().getProjectedView();
Vector3d shaderPos = pos.subtract(cameraPos).scale(1 / getFarPlane());
program.setSphere(shaderPos, 20f / getFarPlane(), 0.01f);
for (int i = 0; i < 16; i++) {
double angle = (Math.PI * AnimationTickHolder.getRenderTime() / 40) + i * Math.PI / 4;
program.addSphere(new SphereFilterProgram.FilterSphere()
.setCenter(pos1.subtract(cameraPos).add(0, 0, i * 30))
.setRadius(15)
.setFeather(0.5f)
.setFilter(ColorMatrices.hueShift((float) i / 16 * 360 + AnimationTickHolder.getRenderTime())));
}
// program.addSphere(new SphereFilterProgram.FilterSphere()
// .setCenter(pos2.subtract(cameraPos))
// .setRadius(50)
// .setFeather(0.5f)
// .setFilter(ColorMatrices.sepia(1)));
//
// program.addSphere(new SphereFilterProgram.FilterSphere()
// .setCenter(pos3.subtract(cameraPos))
// .setRadius(20)
// .setFeather(3f)
// .setFilter(ColorMatrices.saturate(4)));
program.uploadFilters();
program.setFarPlane(getFarPlane());
program.setNearPlane(getNearPlane());
@ -123,7 +150,9 @@ public class EffectsHandler {
program.bindColorTexture(0);
program.bindDepthTexture(0);
GL20.glActiveTexture(GL20.GL_TEXTURE0);
program.clear();
program.unbind();
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, framebuffer.framebufferObject);

View file

@ -1,76 +0,0 @@
package com.simibubi.create.foundation.render.backend.effects;
import org.lwjgl.opengl.GL20;
import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
public class PostProcessingProgram extends GlProgram {
final int uDepth;
final int uColor;
final int uInverseProjection;
final int uInverseView;
final int uNearPlane;
final int uFarPlane;
final int uSphereCenter;
final int uSphereRadius;
final int uSphereFeather;
public PostProcessingProgram(ResourceLocation name, int handle) {
super(name, handle);
uInverseProjection = getUniformLocation("uInverseProjection");
uInverseView = getUniformLocation("uInverseView");
uNearPlane = getUniformLocation("uNearPlane");
uFarPlane = getUniformLocation("uFarPlane");
uSphereCenter = getUniformLocation("uSphereCenter");
uSphereRadius = getUniformLocation("uSphereRadius");
uSphereFeather = getUniformLocation("uSphereFeather");
bind();
uDepth = setSamplerBinding("uDepth", 8);
uColor = setSamplerBinding("uColor", 9);
unbind();
}
public void setNearPlane(float nearPlane) {
GL20.glUniform1f(uNearPlane, nearPlane);
}
public void setFarPlane(float farPlane) {
GL20.glUniform1f(uFarPlane, farPlane);
}
public void setSphere(Vector3d center, float radius, float feather) {
GL20.glUniform3f(uSphereCenter, (float) center.x, (float) center.y, (float) center.z);
GL20.glUniform1f(uSphereRadius, radius);
GL20.glUniform1f(uSphereFeather, feather);
}
public void bindInverseProjection(Matrix4f mat) {
uploadMatrixUniform(uInverseProjection, mat);
}
public void bindInverseView(Matrix4f mat) {
uploadMatrixUniform(uInverseView, mat);
}
public void bindDepthTexture(int textureObject) {
GL20.glActiveTexture(GL20.GL_TEXTURE8);
GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject);
}
public void bindColorTexture(int textureObject) {
GL20.glActiveTexture(GL20.GL_TEXTURE9);
GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject);
}
}

View file

@ -0,0 +1,177 @@
package com.simibubi.create.foundation.render.backend.effects;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL31;
import com.simibubi.create.foundation.render.backend.RenderUtil;
import com.simibubi.create.foundation.render.backend.gl.GlBuffer;
import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
public class SphereFilterProgram extends GlProgram {
protected static final int BLOCK_BINDING = 4;
protected static final int SPHERE_FILTER_SIZE = 4 * 16 + 16 + 4 * 16 * 16;
protected static final int MAX_FILTERS = 16;
protected static final int BUFFER_SIZE = 4 + MAX_FILTERS * SPHERE_FILTER_SIZE;
GlBuffer effectsUBO;
protected final ArrayList<FilterSphere> filters = new ArrayList<>(16);
protected final int uniformBlock;
protected final int uDepth;
protected final int uColor;
protected final int uInverseProjection;
protected final int uInverseView;
protected final int uNearPlane;
protected final int uFarPlane;
// protected final int uSphereCenter;
// protected final int uSphereRadius;
// protected final int uSphereFeather;
// protected final int uColorFilter;
public SphereFilterProgram(ResourceLocation name, int handle) {
super(name, handle);
effectsUBO = new GlBuffer(GL31.GL_UNIFORM_BUFFER);
uniformBlock = GL31.glGetUniformBlockIndex(handle, "Filters");
GL31.glUniformBlockBinding(handle, uniformBlock, BLOCK_BINDING);
effectsUBO.bind();
effectsUBO.alloc(BUFFER_SIZE, GL20.GL_STATIC_DRAW);
GL31.glBindBufferBase(effectsUBO.getBufferType(), BLOCK_BINDING, effectsUBO.handle());
effectsUBO.unbind();
uInverseProjection = getUniformLocation("uInverseProjection");
uInverseView = getUniformLocation("uInverseView");
uNearPlane = getUniformLocation("uNearPlane");
uFarPlane = getUniformLocation("uFarPlane");
//
// uSphereCenter = getUniformLocation("uSphereCenter");
// uSphereRadius = getUniformLocation("uSphereRadius");
// uSphereFeather = getUniformLocation("uSphereFeather");
// uColorFilter = getUniformLocation("uColorFilter");
bind();
uDepth = setSamplerBinding("uDepth", 8);
uColor = setSamplerBinding("uColor", 9);
unbind();
}
public void setNearPlane(float nearPlane) {
GL20.glUniform1f(uNearPlane, nearPlane);
}
public void setFarPlane(float farPlane) {
GL20.glUniform1f(uFarPlane, farPlane);
}
public void clear() {
filters.clear();
}
public void addSphere(FilterSphere filterSphere) {
filters.add(filterSphere);
}
public void uploadFilters() {
effectsUBO.bind(GL20.GL_ARRAY_BUFFER);
effectsUBO.map(GL20.GL_ARRAY_BUFFER, 0, BUFFER_SIZE, this::uploadUBO);
effectsUBO.unbind(GL20.GL_ARRAY_BUFFER);
}
// public void setSphere(FilterSphere sphere) {
// GL20.glUniform3f(uSphereCenter, (float) sphere.center.x, (float) sphere.center.y, (float) sphere.center.z);
//
// GL20.glUniform1f(uSphereRadius, sphere.radius);
// GL20.glUniform1f(uSphereFeather, sphere.feather);
//
// uploadMatrixUniform(uColorFilter, sphere.filter);
// }
public void bindInverseProjection(Matrix4f mat) {
uploadMatrixUniform(uInverseProjection, mat);
}
public void bindInverseView(Matrix4f mat) {
uploadMatrixUniform(uInverseView, mat);
}
public void bindDepthTexture(int textureObject) {
GL20.glActiveTexture(GL20.GL_TEXTURE8);
GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject);
}
public void bindColorTexture(int textureObject) {
GL20.glActiveTexture(GL20.GL_TEXTURE9);
GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject);
}
private void uploadUBO(ByteBuffer buf) {
buf.putInt(filters.size());
buf.position(16);
FloatBuffer floatBuffer = buf.asFloatBuffer();
//floatBuffer.position(4);
filters.forEach(it -> it.write(floatBuffer));
}
public static class FilterSphere {
public Vector3d center;
public float radius;
public float feather;
public Matrix4f filter;
public FilterSphere setCenter(Vector3d center) {
this.center = center;
return this;
}
public FilterSphere setRadius(float radius) {
this.radius = radius;
return this;
}
public FilterSphere setFeather(float feather) {
this.feather = feather;
return this;
}
public FilterSphere setFilter(Matrix4f filter) {
this.filter = filter;
return this;
}
public void write(FloatBuffer buf) {
buf.put(new float[]{
(float) center.x,
(float) center.y,
(float) center.z,
radius,
feather,
0,
0,
0
});
buf.put(RenderUtil.writeMatrix(filter));
}
}
}

View file

@ -22,10 +22,18 @@ public class GlBuffer extends GlObject {
}
public void bind() {
GL20.glBindBuffer(bufferType, handle());
bind(bufferType);
}
public void bind(int type) {
GL20.glBindBuffer(type, handle());
}
public void unbind() {
unbind(bufferType);
}
public void unbind(int bufferType) {
GL20.glBindBuffer(bufferType, 0);
}
@ -47,6 +55,10 @@ public class GlBuffer extends GlObject {
Backend.compat.mapBuffer(bufferType, offset, length, upload);
}
public void map(int type, int offset, int length, Consumer<ByteBuffer> upload) {
Backend.compat.mapBuffer(type, offset, length, upload);
}
protected void deleteInternal(int handle) {
GL20.glDeleteBuffers(handle);
}

View file

@ -0,0 +1,67 @@
#version 140
#flwinclude <"create:core/color.glsl">
in vec2 ScreenCoord;
in vec3 WorldDir;
out vec4 Color;
// constants
uniform sampler2D uDepth;
uniform sampler2D uColor;
uniform float uNearPlane = 0.15;
uniform float uFarPlane = 1.;
struct SphereFilter {
vec4 sphere;// <vec3 position, float radius>
float feather;
mat4 colorOp;
};
#define N 16
layout (std140) uniform Filters {
int uCount;
SphereFilter uSpheres[N];
};
float linearizeDepth(float d, float zNear, float zFar) {
float z_n = 2.0 * d - 1.0;
return 2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear));
}
vec4 filterColor(mat4 colorOp, vec4 frag) {
// preserve alpha while transforming color
vec4 i = vec4(frag.rgb, 1.);
i *= colorOp;
return vec4(i.rgb, frag.a);
}
float getDepth() {
float depth = texture2D(uDepth, ScreenCoord).r;
depth = linearizeDepth(depth, uNearPlane, uFarPlane);
//depth = ( - uNearPlane) / (uFarPlane - uNearPlane);
//depth = depth / uFarPlane;
return depth;
}
void main() {
float depth = getDepth();
vec3 worldPos = WorldDir * depth;
vec4 accum = texture2D(uColor, ScreenCoord);
for (int i = 0; i < uCount; i++) {
SphereFilter s = uSpheres[i];
float distance = distance(s.sphere.xyz, worldPos);
float strength = 1 - smoothstep(s.sphere.w - s.feather, s.sphere.w + s.feather, distance);
accum = mix(accum, filterColor(s.colorOp, accum), strength);
}
Color = accum;
//Color = vec4(vec3(distance / uFarPlane), 1.);
}

View file

@ -0,0 +1,22 @@
#version 140
in vec4 aVertex;// <vec2 position, vec2 texCoords>
out vec2 ScreenCoord;
out vec3 WorldDir;
uniform mat4 uInverseProjection;
uniform mat4 uInverseView;
void main() {
gl_Position = vec4(aVertex.xy, 0., 1.);
ScreenCoord = aVertex.zw;
vec4 clip = vec4(aVertex.xy, 0., 1.);
clip *= uInverseProjection;
vec3 cameraDir = clip.xyz / clip.w;
WorldDir = (uInverseView * vec4(cameraDir, 1.)).xyz;
//worldDirection = (uInverseProjection * vec4(aVertex.xy, 0, 1.)).xyz;
}

View file

@ -1,62 +0,0 @@
#version 120
varying vec4 Vertex;
varying vec3 CameraDir;
//layout (std140) struct Sphere {
// vec4 positionRadius;
// vec4 color;
//} uSphere;
uniform sampler2D uDepth;
uniform sampler2D uColor;
uniform mat4 uInverseProjection;
uniform mat4 uInverseView;
uniform float uNearPlane = 0.15;
uniform float uFarPlane = 1;
uniform vec3 uSphereCenter = vec3(0, 0, 0);
uniform float uSphereRadius = 1;
uniform float uSphereFeather = 0.05;
float linearizeDepth(float d, float zNear, float zFar) {
float z_n = 2.0 * d - 1.0;
return 2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear));
}
vec4 filterColor(vec4 frag) {
const vec3 lum = vec3(0.21, 0.71, 0.07);
float grey = dot(frag.rgb, lum.rgb);
return vec4(grey, grey, grey, frag.a);
}
vec3 getWorldPos(float depth) {
vec3 cameraPos = CameraDir * depth;
vec3 worldPos = (uInverseView * vec4(cameraPos, 1)).xyz;
return worldPos;
}
float getDepth() {
float depth = texture2D(uDepth, Vertex.zw).r;
depth = linearizeDepth(depth, uNearPlane, uFarPlane);
//depth = ( - uNearPlane) / (uFarPlane - uNearPlane);
depth = depth / uFarPlane;
return depth;
}
void main() {
float depth = getDepth();
vec3 worldPos = getWorldPos(depth);
float distance = distance(uSphereCenter, worldPos);
float strength = smoothstep(uSphereRadius - uSphereFeather, uSphereRadius + uSphereFeather, distance);
vec4 fragColor = texture2D(uColor, Vertex.zw);
gl_FragColor = mix(fragColor, filterColor(fragColor), strength);
//gl_FragColor = vec4(worldPos, 1);
}

View file

@ -0,0 +1,22 @@
// All components are in the range [0…1], including hue.
vec3 rgb2hsv(vec3 c) {
const vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
// All components are in the range [0…1], including hue.
vec3 hsv2rgb(vec3 hsv) {
const vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(hsv.xxx + K.xyz) * 6.0 - K.www);
return hsv.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), hsv.y);
}
vec3 hsv2rgbWrapped(vec3 hsv) {
hsv.x = fract(hsv.x);
return hsv2rgb(hsv);
}

View file

@ -1,20 +0,0 @@
#version 120
attribute vec4 aVertex;// <vec2 position, vec2 texCoords>
varying vec4 Vertex;
varying vec3 CameraDir;
uniform mat4 uInverseProjection;
void main() {
gl_Position = vec4(aVertex.xy, 0.0f, 1.0f);
Vertex = aVertex;
vec4 clip = vec4(aVertex.xy, 0, 1);
clip *= uInverseProjection;
CameraDir = clip.xyz / clip.w;
//worldDirection = (uInverseProjection * vec4(aVertex.xy, 0, 1.)).xyz;
}