Merge branch 'shaders' into MC1.12

This commit is contained in:
malte0811 2017-10-10 18:34:22 +02:00
commit d3b937433d
12 changed files with 333 additions and 57 deletions

View file

@ -69,13 +69,13 @@ repositories {
}
dependencies {
compileOnly 'net.industrial-craft:industrialcraft-2:2.8.+'
deobfCompile 'net.industrial-craft:industrialcraft-2:2.8.+'
deobfCompile "blusunrize:ImmersiveEngineering:0.12-+:deobf"
compileOnly "TechReborn:TechReborn-1.12:2.6.+:dev"
compileOnly "RebornCore:RebornCore-1.12:3.2.+:dev"
deobfCompile 'com.elytradev:mirage:2.0.1-SNAPSHOT'
deobfCompile "mezz.jei:jei_1.12:4.+"
deobfCompile "CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.+"
compileOnly "mezz.jei:jei_1.12:4.+"
compileOnly "CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.+"
}
jar {

View file

@ -66,5 +66,7 @@ public class IWConfig {
@Comment({"The effect of standing somewhat close to a Marx generator discharge.",
"0: Tinnitus, 1: Nausea, 2: normal damage"})
public static int marxSoundDamage = 0;
@Comment({"Set to false to disable shaders. They are used for rendering the Marx generator and the Jacob's ladder."})
public static boolean enableShaders = true;
}
}

View file

@ -65,7 +65,7 @@ import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
//TODO require IE 0.12-72
@Mod(modid = IndustrialWires.MODID, version = IndustrialWires.VERSION, dependencies = "required-after:immersiveengineering@[0.12-72,);after:ic2",
certificateFingerprint = "7e11c175d1e24007afec7498a1616bef0000027d")
@Mod.EventBusSubscriber

View file

@ -548,12 +548,12 @@ public class TileEntityJacobsLadder extends TileEntityIEBase implements ITickabl
public static final float[] saltColor = {1, 190 / 255F, 50 / 255F};
public static final float[] airColor = {1, .85F, 1};
private static final int factor = 20;
private static final double smallMin = Math.exp(-.5);
private static final double normalMin = Math.exp(-.25 * factor);
private static final double hugeMin = Math.exp(-.75 * factor);
public static float[] getColor(double t, double salt, LadderSize size) {
salt = Math.min(salt, 1);
int factor = 20;
double smallMin = Math.exp(-.5);
double normalMin = Math.exp(-.25 * factor);
double hugeMin = Math.exp(-.75 * factor);
double saltyness = 0;
double t2 = t - .5;
switch (size) {

View file

@ -50,6 +50,7 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagDouble;
@ -296,7 +297,7 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
energyStored = -energyStored;
} else {
int seed = Utils.RAND.nextInt();
genDischarge((float) energyStored, seed);//TODO test on a dedicated server
genDischarge((float) energyStored, seed);
data.setInteger("randSeed", seed);
handleEntities(energyStored);
handleOreProcessing(energyStored);//After entities to prevent killing the newly dropped items
@ -687,15 +688,15 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
if (master.capVoltages!=null&&master.capVoltages.length==stageCount) {
int signalTop = getRSSignalFromVoltage(master.capVoltages[stageCount-1]);
int signalBottom = getRSSignalFromVoltage(master.capVoltages[0]);
setSignal(ORANGE.getMetadata(), (signalBottom>>4)&0xf, signals);
setSignal(MAGENTA.getMetadata(), (signalTop>>4)&0xf, signals);
setSignal(LIME.getMetadata(), signalBottom&0xf, signals);
setSignal(PINK.getMetadata(), signalTop&0xf, signals);
setSignal(ORANGE, (signalBottom>>4)&0xf, signals);
setSignal(MAGENTA, (signalTop>>4)&0xf, signals);
setSignal(LIME, signalBottom&0xf, signals);
setSignal(PINK, signalTop&0xf, signals);
}
}
private void setSignal(int channel, int value, byte[] signals) {
signals[channel] = (byte) Math.max(value, signals[channel]);
private void setSignal(EnumDyeColor channel, int value, byte[] signals) {
signals[channel.getMetadata()] = (byte) Math.max(value, signals[channel.getMetadata()]);
}
public void setStageCount(int stageCount) {
@ -759,11 +760,7 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
final int stageCount;
Discharge(int stages) {
stageCount = stages;
int count = 1;
while (count<stageCount) {
count <<= 1;
}
count = 8;
int count = stages/5+1;
vertices = new Vec3d[2*count];
vertices[0] = new Vec3d(0, -.5F, 0);
for (int i = 1;i<vertices.length;i++) {
@ -775,10 +772,6 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
// Meant to be const
private final Vec3d side = new Vec3d(0, 0, 1);
//used for calculation buffering
private Vec3d diff;
private Vec3d center;
private Vec3d v0;
private Matrix4 transform = new Matrix4();
void genMarxPoint(int randSeed) {
@ -790,8 +783,8 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
*/
void genMarxPoint(int min, int max, Random rand) {
int toGenerate = (min+max)/2;
diff = vertices[max].subtract(vertices[min]);
v0 = diff.crossProduct(side);
Vec3d diff = vertices[max].subtract(vertices[min]);
Vec3d v0 = diff.crossProduct(side);
transform.setIdentity();
double diffLength = diff.lengthVector();
double noise = Math.sqrt(diffLength)*rand.nextDouble()*1/(1+Math.abs(stageCount/2.0-toGenerate))*.75;
@ -801,7 +794,7 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
v0 = v0.scale((float) (noise/v0.lengthVector()));
diff = diff.scale(1/diffLength);
transform.rotate(Math.PI*2*rand.nextDouble(), diff.x, diff.y, diff.z);
center = vertices[max].add(vertices[min]).scale(.5);
Vec3d center = vertices[max].add(vertices[min]).scale(.5);
vertices[toGenerate] = transform.apply(v0);
vertices[toGenerate] = center.add(vertices[toGenerate]);

View file

@ -41,6 +41,7 @@ import malte0811.industrialWires.client.gui.GuiPanelCreator;
import malte0811.industrialWires.client.gui.GuiRSPanelConn;
import malte0811.industrialWires.client.gui.GuiRenameKey;
import malte0811.industrialWires.client.panelmodel.PanelModelLoader;
import malte0811.industrialWires.client.render.Shaders;
import malte0811.industrialWires.client.render.TileRenderJacobsLadder;
import malte0811.industrialWires.client.render.TileRenderMarx;
import malte0811.industrialWires.controlpanel.PanelComponent;
@ -118,6 +119,7 @@ public class ClientProxy extends CommonProxy {
ModelLoaderRegistry.registerLoader(new PanelModelLoader());
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityJacobsLadder.class, new TileRenderJacobsLadder());
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMarx.class, new TileRenderMarx());
Shaders.initShaders(true);
}
@Override

View file

@ -0,0 +1,176 @@
/*
* This file is part of Industrial Wires.
* Copyright (C) 2016-2017 malte0811
* Industrial Wires is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* Industrial Wires is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Industrial Wires. If not, see <http://www.gnu.org/licenses/>.
*/
package malte0811.industrialWires.client.render;
import blusunrize.immersiveengineering.api.IEApi;
import malte0811.industrialWires.IWConfig;
import malte0811.industrialWires.IndustrialWires;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.OpenGlHelper;
import org.lwjgl.opengl.ARBFragmentShader;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.GL11;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Shaders
{
public static int JACOBS_ARC;
public static int MARX;
private static String PREFIX = "/assets/"+ IndustrialWires.MODID+"/shaders/";
public static void initShaders(boolean setupReload) {
if (areShadersEnabled()) {
JACOBS_ARC = createProgram(null, PREFIX + "jacobs.frag");
MARX = createProgram(null, PREFIX + "marx.frag");
if (setupReload) {
IEApi.renderCacheClearers.add(() -> {
if (JACOBS_ARC != 0) {
deleteShader(JACOBS_ARC);
JACOBS_ARC = 0;
}
if (MARX != 0) {
deleteShader(MARX);
MARX = 0;
}
initShaders(false);
});
}
}
}
//All stolen from Botania...
private static final int VERT = ARBVertexShader.GL_VERTEX_SHADER_ARB;
private static final int FRAG = ARBFragmentShader.GL_FRAGMENT_SHADER_ARB;
private static void deleteShader(int id) {
if (id != 0) {
ARBShaderObjects.glDeleteObjectARB(id);
}
}
public static void useShader(int shader) {
if (areShadersEnabled()) {
ARBShaderObjects.glUseProgramObjectARB(shader);
if (shader != 0) {
int time = ARBShaderObjects.glGetUniformLocationARB(shader, "time");
ARBShaderObjects.glUniform1fARB(time, Minecraft.getMinecraft().world.getTotalWorldTime() + Minecraft.getMinecraft().getRenderPartialTicks());
}
}
}
public static void stopUsingShaders() {
useShader(0);
}
private static int createProgram(String vert, String frag) {
int vertId = 0, fragId = 0, program;
if(vert != null)
vertId = createShader(vert, VERT);
if(frag != null)
fragId = createShader(frag, FRAG);
program = ARBShaderObjects.glCreateProgramObjectARB();
if(program == 0)
return 0;
if(vert != null)
ARBShaderObjects.glAttachObjectARB(program, vertId);
if(frag != null)
ARBShaderObjects.glAttachObjectARB(program, fragId);
ARBShaderObjects.glLinkProgramARB(program);
if(ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
IndustrialWires.logger.error(getLogInfo(program));
return 0;
}
ARBShaderObjects.glValidateProgramARB(program);
if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) {
IndustrialWires.logger.error(getLogInfo(program));
return 0;
}
return program;
}
private static int createShader(String filename, int shaderType){
int shader = 0;
try {
shader = ARBShaderObjects.glCreateShaderObjectARB(shaderType);
if(shader == 0)
return 0;
ARBShaderObjects.glShaderSourceARB(shader, readFileAsString(filename));
ARBShaderObjects.glCompileShaderARB(shader);
if (ARBShaderObjects.glGetObjectParameteriARB(shader, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE)
throw new RuntimeException("Error creating shader: " + getLogInfo(shader));
return shader;
}
catch(Exception e) {
ARBShaderObjects.glDeleteObjectARB(shader);
e.printStackTrace();
return -1;
}
}
private static String getLogInfo(int obj) {
return ARBShaderObjects.glGetInfoLogARB(obj, ARBShaderObjects.glGetObjectParameteriARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB));
}
private static String readFileAsString(String filename) throws Exception {
InputStream in = Shaders.class.getResourceAsStream(filename);
if(in == null)
return "";
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"))) {
return preProcess(reader.lines());
}
}
public static boolean areShadersEnabled() {
return IWConfig.HVStuff.enableShaders && OpenGlHelper.shadersSupported;
}
/*
* Custom PreProcessor, I need random a lot and wanted #include
*/
private static String preProcess(Stream<String> lines) {
lines = lines.map((s)->{
if (s.startsWith("#include ")) {
s = s.substring("#include ".length());
String fileName = PREFIX +s;
try {
return readFileAsString(fileName);
} catch (Exception e) {
throw new RuntimeException(fileName+" not readable", e);
}
}
return s;
});
return lines.collect(Collectors.joining("\n"));
}
}

View file

@ -41,17 +41,20 @@ public class TileRenderJacobsLadder extends TileEntitySpecialRenderer<TileEntity
GlStateManager.translate(x + .5, y + tile.size.heightOffset, z + .5);
GlStateManager.rotate(tile.facing.getHorizontalAngle(), 0, 1, 0);
GlStateManager.translate(-tile.size.bottomDistance / 2, 0, 0);
GlStateManager.disableTexture2D();
GlStateManager.disableLighting();
GlStateManager.shadeModel(GL11.GL_SMOOTH);
if (Shaders.areShadersEnabled()) {
GlStateManager.enableBlend();
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
}
setLightmapDisabled(true);
GlStateManager.color(1, .85F, 1, 1);
Vec3d[] controls = new Vec3d[tile.size.arcPoints];
for (int i = 0; i < tile.size.arcPoints; i++) {
Vec3d speed = tile.controlMovement[i];
controls[i] = tile.controls[i].addVector(speed.x * partialTicks, speed.y * partialTicks, speed.z * partialTicks);
Vec3d speed = tile.controlMovement[i].scale(partialTicks);
controls[i] = tile.controls[i].add(speed);
}
drawBezier(controls, tile.salt, tile.size);
//DEBUG CODE
@ -74,12 +77,14 @@ public class TileRenderJacobsLadder extends TileEntitySpecialRenderer<TileEntity
GlStateManager.enableTexture2D();
GlStateManager.enableLighting();
GlStateManager.shadeModel(GL11.GL_FLAT);
GlStateManager.disableBlend();
GlStateManager.popMatrix();
}
}
private void drawBezier(Vec3d[] controls, double salt, LadderSize size) {
Shaders.useShader(Shaders.JACOBS_ARC);
int steps = size.renderPoints;
double diameter = size.renderDiameter;
Vec3d radY = new Vec3d(0, diameter / 2, 0);
@ -90,31 +95,41 @@ public class TileRenderJacobsLadder extends TileEntitySpecialRenderer<TileEntity
vertBuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
Vec3d last = Beziers.getPoint(0, controls);
colors[0] = getColor(0, salt, size);
if (Shaders.areShadersEnabled()) {
colors[0][0] = 0;
}
for (int i = 1; i <= steps; i++) {
double d = i / (double) steps;
colors[i] = getColor(d, salt, size);
Vec3d pos = Beziers.getPoint(d, controls);
drawQuad(last, pos, radY, colors[i - 1], colors[i], vertBuffer);
drawQuad(last, pos, radZ, colors[i - 1], colors[i], vertBuffer);
if (Shaders.areShadersEnabled()) {
colors[i][0] = (float) d;
}
drawQuad(last, pos, radY, colors[i - 1], colors[i], vertBuffer, false);
drawQuad(last, pos, radZ, colors[i - 1], colors[i], vertBuffer, false);
last = pos;
}
tes.draw();
Shaders.stopUsingShaders();
}
private void drawQuad(Vec3d v0, Vec3d v1, Vec3d rad, float[] color0, float[] color1, BufferBuilder vertexBuffer) {
color(color1, vertexBuffer.pos(v1.x - rad.x, v1.y - rad.y, v1.z - rad.z)).endVertex();
color(color0, vertexBuffer.pos(v0.x - rad.x, v0.y - rad.y, v0.z - rad.z)).endVertex();
color(color0, vertexBuffer.pos(v0.x + rad.x, v0.y + rad.y, v0.z + rad.z)).endVertex();
color(color1, vertexBuffer.pos(v1.x + rad.x, v1.y + rad.y, v1.z + rad.z)).endVertex();
private void drawQuad(Vec3d v0, Vec3d v1, Vec3d rad, float[] color0, float[] color1, BufferBuilder vertexBuffer,
boolean horizontal) {
float alpha0 = horizontal?.5F:0;
float alpha1 = horizontal?.5F:1;
color(color1, alpha0, vertexBuffer.pos(v1.x - rad.x, v1.y - rad.y, v1.z - rad.z)).endVertex();
color(color0, alpha0, vertexBuffer.pos(v0.x - rad.x, v0.y - rad.y, v0.z - rad.z)).endVertex();
color(color0, alpha1, vertexBuffer.pos(v0.x + rad.x, v0.y + rad.y, v0.z + rad.z)).endVertex();
color(color1, alpha1, vertexBuffer.pos(v1.x + rad.x, v1.y + rad.y, v1.z + rad.z)).endVertex();
color(color1, vertexBuffer.pos(v1.x + rad.x, v1.y + rad.y, v1.z + rad.z)).endVertex();
color(color0, vertexBuffer.pos(v0.x + rad.x, v0.y + rad.y, v0.z + rad.z)).endVertex();
color(color0, vertexBuffer.pos(v0.x - rad.x, v0.y - rad.y, v0.z - rad.z)).endVertex();
color(color1, vertexBuffer.pos(v1.x - rad.x, v1.y - rad.y, v1.z - rad.z)).endVertex();
color(color1, alpha1, vertexBuffer.pos(v1.x + rad.x, v1.y + rad.y, v1.z + rad.z)).endVertex();
color(color0, alpha1, vertexBuffer.pos(v0.x + rad.x, v0.y + rad.y, v0.z + rad.z)).endVertex();
color(color0, alpha0, vertexBuffer.pos(v0.x - rad.x, v0.y - rad.y, v0.z - rad.z)).endVertex();
color(color1, alpha0, vertexBuffer.pos(v1.x - rad.x, v1.y - rad.y, v1.z - rad.z)).endVertex();
}
private BufferBuilder color(float[] color, BufferBuilder vb) {
vb.color(color[0], color[1], color[2], 1);
private BufferBuilder color(float[] color, float alpha, BufferBuilder vb) {
vb.color(color[0], color[1], color[2], alpha);
return vb;
}
}

View file

@ -94,7 +94,8 @@ public class TileRenderMarx extends TileEntitySpecialRenderer<TileEntityMarx> {
}
GlStateManager.rotate(angle, 0, 1, 0);
vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
drawDischargeSection(new Vec3d(0, -.2F, 0), new Vec3d(0, .2F, 0), .25F, vb);
drawDischargeSection(new Vec3d(0, -.2F, 0), new Vec3d(0, .2F, 0), .25F,
.4F, .45F, vb);
tes.draw();
GlStateManager.popMatrix();
}
@ -116,6 +117,7 @@ public class TileRenderMarx extends TileEntitySpecialRenderer<TileEntityMarx> {
Matrix4 ret = new Matrix4();
ret.rotate(-angle, 0, 1, 0);
GlStateManager.rotate((float) Math.toDegrees(angle), 0, 1, 0);
Shaders.useShader(Shaders.MARX);
return ret;
}
private void cleanUp() {
@ -125,29 +127,35 @@ public class TileRenderMarx extends TileEntitySpecialRenderer<TileEntityMarx> {
GlStateManager.enableLighting();
GlStateManager.shadeModel(GL11.GL_FLAT);
GlStateManager.disableBlend();
Shaders.stopUsingShaders();
}
private static final float[] WHITE = {1, 1, 1, 1};
private static final float[] WHITE_TRANSPARENT = {1, 1, 1, 0};
private void drawDischarge(Discharge d, BufferBuilder vb, Tessellator tes, Matrix4 mat) {
if (d!=null&&d.vertices!=null) {
vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
for (int i = 0;i<d.vertices.length-1;i++) {
drawDischargeSection(mat.apply(d.vertices[i]), mat.apply(d.vertices[i+1]), d.diameter, vb);
drawDischargeSection(mat.apply(d.vertices[i]), mat.apply(d.vertices[i+1]), d.diameter,
i/(float)(d.vertices.length-1), (i+1)/(float)(d.vertices.length-1), vb);
}
tes.draw();
}
}
private void drawDischargeSection(Vec3d start, Vec3d end, float diameter, BufferBuilder vb) {
drawPart(start, end, diameter/3, diameter/3, WHITE_TRANSPARENT, WHITE, vb);
drawPart(start, end, 0, diameter/3, WHITE, WHITE, vb);
drawPart(start, end, -diameter/3, diameter/3, WHITE, WHITE_TRANSPARENT, vb);
private void drawDischargeSection(Vec3d start, Vec3d end, float diameter, float aMin, float aMax, BufferBuilder vb) {
if (Shaders.areShadersEnabled()) {
drawPart(0, diameter, start, end, aMin, aMax, vb);
} else {
drawPart(-diameter/3, diameter/3, start, end, 0, 1, vb);
drawPart(0, diameter/3, start, end, 1, 1, vb);
drawPart(diameter/3, diameter/3, start, end, 1, 0, vb);
}
}
private void drawPart(Vec3d start, Vec3d end, float offset, float width, float[] color1, float[] color2, BufferBuilder vb) {
vb.setTranslation(-offset-width/2, 0, 0);
vb.pos(start.x, start.y, start.z).color(color1[0], color1[1], color1[2], color1[3]).endVertex();
vb.pos(start.x+width, start.y, start.z).color(color2[0], color2[1], color2[2], color2[3]).endVertex();
vb.pos(end.x+width, end.y, end.z).color(color2[0], color2[1], color2[2], color2[3]).endVertex();
vb.pos(end.x, end.y, end.z).color(color1[0], color1[1], color1[2], color1[3]).endVertex();
private void drawPart(double offset, double diameter, Vec3d start, Vec3d end, float aMin, float aMax, BufferBuilder vb) {
boolean shaders = Shaders.areShadersEnabled();
float red1 = shaders?0:1;
vb.setTranslation(offset-diameter/2, 0, 0);
vb.pos(start.x, start.y, start.z).color(red1, 1, 1, aMin).endVertex();
vb.pos(start.x+diameter, start.y, start.z).color(1, 1, 1, shaders?aMin:aMax).endVertex();
vb.pos(end.x+diameter, end.y, end.z).color(1, 1, 1, aMax).endVertex();
vb.pos(end.x, end.y, end.z).color(red1, 1, 1, shaders?aMax:aMin).endVertex();
vb.setTranslation(0, 0, 0);
}
}

View file

@ -0,0 +1,11 @@
#version 120
uniform float time;
#include random.frag
void main() {
float height = 2*(gl_Color.a-.5);
float x = gl_Color.r;
height += .5*cnoise(vec2(x*10, time*.5));
gl_FragColor = gl_Color;
gl_FragColor.r = 1;
gl_FragColor.a = 1-height*height;
}

View file

@ -0,0 +1,9 @@
#version 120
uniform float time;
#include random.frag
void main() {
float x = 2*(gl_Color.r-.5);
float y = gl_Color.a;
x -= .5*cnoise(vec2(10*y, time));
gl_FragColor = vec4(1, 1, 1, 1-abs(x));
}

View file

@ -0,0 +1,60 @@
//Noise generation code taken from https://github.com/ashima/webgl-noise/blob/master/src/classicnoise2D.glsl
vec4 mod289(vec4 x)
{
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 permute(vec4 x)
{
return mod289(((x*34.0)+1.0)*x);
}
vec4 taylorInvSqrt(vec4 r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
vec2 fade(vec2 t) {
return t*t*t*(t*(t*6.0-15.0)+10.0);
}
// Classic Perlin noise
float cnoise(vec2 P)
{
vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
Pi = mod289(Pi); // To avoid truncation effects in permutation
vec4 ix = Pi.xzxz;
vec4 iy = Pi.yyww;
vec4 fx = Pf.xzxz;
vec4 fy = Pf.yyww;
vec4 i = permute(permute(ix) + iy);
vec4 gx = fract(i * (1.0 / 41.0)) * 2.0 - 1.0 ;
vec4 gy = abs(gx) - 0.5 ;
vec4 tx = floor(gx + 0.5);
gx = gx - tx;
vec2 g00 = vec2(gx.x,gy.x);
vec2 g10 = vec2(gx.y,gy.y);
vec2 g01 = vec2(gx.z,gy.z);
vec2 g11 = vec2(gx.w,gy.w);
vec4 norm = taylorInvSqrt(vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
g00 *= norm.x;
g01 *= norm.y;
g10 *= norm.z;
g11 *= norm.w;
float n00 = dot(g00, vec2(fx.x, fy.x));
float n10 = dot(g10, vec2(fx.y, fy.y));
float n01 = dot(g01, vec2(fx.z, fy.z));
float n11 = dot(g11, vec2(fx.w, fy.w));
vec2 fade_xy = fade(Pf.xy);
vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
return 2.3 * n_xy;
}