Skip to content

Commit

Permalink
Merge pull request #39 from shader-slang/lsp
Browse files Browse the repository at this point in the history
More demo updates.
  • Loading branch information
csyonghe authored Nov 8, 2024
2 parents a5e60a5 + 261e2c2 commit 394e661
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 84 deletions.
57 changes: 57 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"files.associations": {
"xstring": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"exception": "cpp",
"format": "cpp",
"initializer_list": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"memory": "cpp",
"new": "cpp",
"ostream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"utility": "cpp",
"vector": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xtr1common": "cpp",
"xutility": "cpp"
}
}
56 changes: 43 additions & 13 deletions demos/circle.slang
Original file line number Diff line number Diff line change
@@ -1,20 +1,50 @@
// A simple shader ported from https://www.shadertoy.com/view/XdlSDs.
// Author: dynamite

import playground;

typealias vec2 = float2;
typealias vec3 = float3;
typealias vec4 = float4;

float4 imageMain(uint2 dispatchThreadID, int2 screenSize)
{
float2 size = float2(screenSize.x, screenSize.y);
float2 center = size / 2.0;

float2 pos = float2(dispatchThreadID.xy);

float stripSize = screenSize.x / 40;
vec2 p = (dispatchThreadID.xy * 2 - screenSize.xy) / (float)screenSize.y;
float tau = float.getPi() * 2.0;
float a = atan2(p.x,p.y);
float r = length(p)*0.75;
vec2 uv = vec2(a/tau,r);

float time = getTime() * 0.2;

const float time = getTime(); // from playgournd
float dist = distance(pos, center) + time;
float strip = dist / stripSize % 2.0;
//get the color
float xCol = (uv.x - time/3) * 3.0;
xCol = fmod(abs(xCol), 3.0f);
vec3 horColour = vec3(0.25, 0.25, 0.25);

if (xCol < 1.0)
{
horColour.r += 1.0 - xCol;
horColour.g += xCol;
}
else if (xCol < 2.0)
{
xCol -= 1.0;
horColour.g += 1.0 - xCol;
horColour.b += xCol;
}
else
{
xCol -= 2.0;
horColour.b += 1.0 - xCol;
horColour.r += xCol;
}

if (strip < 1.0f)
return float4(1.0f, 0.0f, 0.0f, 1.0f);
else
return float4(0.0f, 1.0f, 1.0f, 1.0f);
// draw color beam
uv = (2.0 * uv) - 1.0;
float beamWidth = (0.7 +
0.5 * cos(uv.x * 10.0 * tau * 0.15 * clamp(floor(5.0 + 10.0 * cos(time)), 0.0, 10.0)))
* abs(1.0 / (30.0 * uv.y));
vec3 horBeam = vec3(beamWidth);
return vec4(((horBeam) * horColour), 1.0);
}
4 changes: 2 additions & 2 deletions demos/demo-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ var demoList = [
{ name: "Simple Print", url: "simple-print.slang" },
{ name: "Simple Image", url: "simple-image.slang" },
{ name: "-", url: "" },
{ name: "Circle", url: "circle.slang" },
{ name: "Ocean", url: "ocean.slang" }
{ name: "ShaderToy: Circle", url: "circle.slang" },
{ name: "ShaderToy: Ocean", url: "ocean.slang" }
];
39 changes: 25 additions & 14 deletions demos/ocean.slang
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
// The ocean shader from ShaderToys by afl_ext.
// https://www.shadertoy.com/view/MdXyzX

// This shader is modified to use Slang's automatic differentiation feature
// to compute the normal of the wave by differentiating the `getwaves` function
// with regard to `position`. See `normal` function for how autodiff is used.

// afl_ext 2017-2024
// MIT License
import playground;
Expand All @@ -10,28 +17,37 @@ static const int ITERATIONS_NORMAL = 37; // waves iterations when calculating no

// Calculates wave value and its derivative,
// for the wave direction, position in space, wave frequency and time
[Differentiable]
[PreferCheckpoint]
float2 wavedx(float2 position, float2 direction, float frequency, float timeshift) {
float x = dot(direction, position) * frequency + timeshift;
float wave = exp(sin(x) - 1.0);
float dx = wave * cos(x);
return float2(wave, -dx);
}

// Calculates waves by summing octaves of various waves with various parameters
float getwaves(float2 position, int iterations) {
// Calculates waves by summing octaves of various waves with various parameters.
// This function is a generic function that can be specialized by different number of iterations.
[Differentiable]
float getwaves<int iterations>(float2 position) {
float wavePhaseShift = length(position) * 0.1; // this is to avoid every octave having exactly the same phase everywhere
float iter = 0.0; // this will help generating well distributed wave directions
float frequency = 1.0; // frequency of the wave, this will change every iteration
float timeMultiplier = 0.5; // time multiplier for the wave, this will change every iteration
float weight = 1.0;// weight in final sum for the wave, this will change every iteration
float sumOfValues = 0.0; // will store final sum of values
float sumOfWeights = 0.0; // will store final sum of weights
[ForceUnroll]
for(int i=0; i < iterations; i++) {
// generate some wave direction that looks kind of random
float2 p = float2(sin(iter), cos(iter));

// calculate wave data
float2 res = wavedx(position, p, frequency, getTime() * timeMultiplier + wavePhaseShift);

// Since we don't need to propagate gradient through time and `getTime()` is a non-differentiable
// function, we need to use `no_diff` here to express our intention that we don't need gradients
// to propagate through the call.
float2 res = wavedx(position, p, frequency, no_diff getTime() * timeMultiplier + wavePhaseShift);

// shift position around according to wave drag and derivative of the wave
position += p * res.y * weight * DRAG_MULT;
Expand All @@ -58,7 +74,7 @@ float raymarchwater(float3 camera, float3 start, float3 end, float depth) {
float3 dir = normalize(end - start);
for(int i=0; i < 64; i++) {
// the height is from 0 to -depth
float height = getwaves(pos.xz, ITERATIONS_RAYMARCH) * depth - depth;
float height = getwaves<ITERATIONS_RAYMARCH>(pos.xz) * depth - depth;
// if the waves height almost nearly matches the ray height, assume its a hit and return the hit distance
if(height + 0.01 > pos.y) {
return distance(pos, camera);
Expand All @@ -71,17 +87,12 @@ float raymarchwater(float3 camera, float3 start, float3 end, float depth) {
return distance(start, camera);
}

// Calculate normal at point by calculating the height at the pos and 2 additional points very close to pos
// Calculate normal at point by using autodiff to get the derivative of `getwave` function
// with regard to `position`.
float3 normal(float2 pos, float e, float depth) {
float2 ex = float2(e, 0);
float H = getwaves(pos.xy, ITERATIONS_NORMAL) * depth;
float3 a = float3(pos.x, H, pos.y);
return normalize(
cross(
a - float3(pos.x - e, getwaves(pos.xy - ex.xy, ITERATIONS_NORMAL) * depth, pos.y),
a - float3(pos.x, getwaves(pos.xy + ex.yx, ITERATIONS_NORMAL) * depth, pos.y + e)
)
);
DifferentialPair<float2> diffPos = diffPair(pos);
bwd_diff(getwaves<ITERATIONS_NORMAL>)(diffPos, 1.0);
return normalize(float3(-diffPos.d.x, 1.0, -diffPos.d.y));
}

// Helper function generating a rotation matrix around the axis by the angle
Expand Down
37 changes: 9 additions & 28 deletions try-slang.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,10 @@ var currentWindowSize = [300, 150];
const RENDER_MODE = SlangCompiler.RENDER_SHADER;
const PRINT_MODE = SlangCompiler.PRINT_SHADER;
const HIDDEN_MODE = SlangCompiler.NON_RUNNABLE_SHADER;
const defaultShaderURL = "circle.slang";

var currentMode = RENDER_MODE;

// TODO: Question?
// When we generate the shader code to wgsl, the uniform variable (float time) will have 16 bytes alignment, which is not shown in the slang
// code. So how the user can know the correct alignment of the uniform variable without using the slang reflection API or
// looking at the generated shader code?
const defaultShaderCode = `
import playground;
float4 imageMain(uint2 dispatchThreadID, int2 screenSize)
{
float2 size = float2(screenSize.x, screenSize.y);
float2 center = size / 2.0;
float2 pos = float2(dispatchThreadID.xy);
float stripSize = screenSize.x / 40;
const float time = getTime(); // from playgournd
float dist = distance(pos, center) + time;
float strip = dist / stripSize % 2.0;
if (strip < 1.0f)
return float4(1.0f, 0.0f, 0.0f, 1.0f);
else
return float4(0.0f, 1.0f, 1.0f, 1.0f);
}
`;

async function webgpuInit()
{
const adapter = await navigator.gpu?.requestAdapter();
Expand Down Expand Up @@ -508,7 +482,14 @@ function runIfFullyInitialized()

if (device)
{
compileOrRun();
if (monacoEditor.getValue() == "")
{
loadDemo(defaultShaderURL);
}
else
{
compileOrRun();
}
}
}
}
56 changes: 29 additions & 27 deletions ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,34 +137,36 @@ function initializeModal() {
};
}

function loadDemo(selectedDemoURL) {
if (selectedDemoURL != "")
{
// Is `selectedDemoURL` a relative path?
var finalURL;
if (!selectedDemoURL.startsWith("http"))
{
// If so, append the current origin to it.
// Combine the url to point to demos/${selectedDemoURL}.
finalURL = new URL("demos/" + selectedDemoURL, window.location.href);
}
else
{
finalURL = new URL(selectedDemoURL);
}
// Retrieve text from selectedDemoURL.
fetch(finalURL)
.then((response) => response.text())
.then((data) => {
monacoEditor.setValue(data);
compileOrRun();
});
}
}

function handleDemoDropdown() {
const demoDropdown = document.getElementById("demo-dropdown");
const selectInput = demoDropdown.querySelector(".dropdown-select");
const selectInput = document.getElementById("demo-select");

selectInput.addEventListener("change", function () {
var selectedDemoURL = this.value;
if (selectedDemoURL != "")
{
// Is `selectedDemoURL` a relative path?
var finalURL;
if (!selectedDemoURL.startsWith("http"))
{
// If so, append the current origin to it.
// Combine the url to point to demos/${selectedDemoURL}.
finalURL = new URL("demos/" + selectedDemoURL, window.location.href);
}
else
{
finalURL = new URL(selectedDemoURL);
}
// Retrieve text from selectedDemoURL.
fetch(finalURL)
.then((response) => response.text())
.then((data) => {
monacoEditor.setValue(data);
compileOrRun();
});
}
loadDemo(this.value);
});
}

Expand Down Expand Up @@ -206,7 +208,7 @@ function loadDemoList()
}

document.addEventListener("DOMContentLoaded", function () {
var initShaderCode = defaultShaderCode;
var initShaderCode = "";
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
if (code) {
Expand All @@ -216,7 +218,7 @@ document.addEventListener("DOMContentLoaded", function () {
});
}
else {
loadEditor(false, "codeEditor", defaultShaderCode);
loadEditor(false, "codeEditor", initShaderCode);
}
loadEditor(true, "diagnostics", "Diagnostic Output");
loadEditor(true, "codeGen", "Generated Target Code");
Expand Down

0 comments on commit 394e661

Please sign in to comment.