%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% NotITG Lua and more notes %% %% -CraftedCart %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% = Contents = - [[#Shaders|Shaders]] - [[#Shaders#Default shaders (I think?)|Default shaders (I think?)]] - [[#Shaders#Default shaders (I think?)#Vertex shader 1|Vertex shader 1]] - [[#Shaders#Default shaders (I think?)#Vertex shader 2|Vertex shader 2]] - [[#Shaders#Default shaders (I think?)#Fragment shader|Fragment shader]] - [[#Shaders#Misc tidbits|Misc tidbits]] - [[#Shaders#Actor methods|Actor methods]] - [[#Shaders#Shader methods|Shader methods]] - [[#Shaders#How the heck did I find these?|How the heck did I find these?]] - [[#Arrow path splines|Arrow path splines]] - [[#Arrow path splines#Player methods|Player methods]] - [[#Path, arrow, and stealth gradients|Path, arrow, and stealth gradients]] - [[#Hide the default UI|Hide the default UI]] - [[#Mods|Mods]] - [[#Mods#How mod strings work|How mod strings work]] - [[#3D models|3D models]] - [[#ActorFrame|ActorFrame]] = Shaders = Shaders can be applied to actors with the Vert and Frag XML attributes. You don't need to specify both attrubutes, you can specify one and NotITG will use the default for the other. {{{xml }}} == Default shaders (I think?) == I ended up finding two vertex shaders - not sure which one is used where. === Vertex shader 1 === {{{glsl attribute vec4 TextureMatrixScale; void main() { gl_Position = (gl_ModelViewProjectionMatrix * gl_Vertex); gl_TexCoord[0] = (gl_TextureMatrix[0] * gl_MultiTexCoord0 * TextureMatrixScale) + (gl_MultiTexCoord0 * (vec4(1)-TextureMatrixScale)); gl_FrontColor = gl_Color; } }}} === Vertex shader 2 === {{{glsl attribute vec4 TextureMatrixScale; varying vec3 position; varying vec3 normal; varying vec4 color; varying vec2 textureCoord; varying vec2 imageCoord; uniform vec2 textureSize; uniform vec2 imageSize; uniform mat4 textureMatrix; void main() { normal = gl_NormalMatrix * gl_Normal * vec3(1.0, -1.0, 1.0); gl_Position = (gl_ModelViewProjectionMatrix * gl_Vertex); position = gl_Vertex.xyz; gl_TexCoord[0] = (textureMatrix * gl_MultiTexCoord0 * TextureMatrixScale) + (gl_MultiTexCoord0 * (vec4(1)-TextureMatrixScale)); textureCoord = ((textureMatrix * gl_MultiTexCoord0 * TextureMatrixScale) + (gl_MultiTexCoord0 * (vec4(1)-TextureMatrixScale))).xy; imageCoord = textureCoord * textureSize / imageSize; gl_FrontColor = gl_Color; color = gl_Color; } }}} === Fragment shader === {{{glsl uniform sampler2D sampler0; varying vec2 textureCoord; varying vec4 color; void main (void) { gl_FragColor = texture2D(sampler0, textureCoord) * color; } }}} == Misc tidbits == - The StepMania 5 `RageDisplay.cpp` and `RageDisplayOGL.cpp` files are a good place to look if you want to add matrix math into your stepfiles - Texture dimensions must be powers of two... unless you like empty padding - `imageSize` is the dimensions of a texture _without padding_ - eg: a 200x200 image will have an image size of 200x200 - NotITG adds padding around images whose dimensions aren't powers of two - `textureSize` is the dimensions of a texture of the GPU, with padding - eg: a 200x200 image will have a texture size of 256x256 == Actor methods == - `GetShader()` - Return a `RageShaderProgram` object - `SetShader(shader)` - Set the shader for this actor - `shader` should be a `RageShaderProgram` object == Shader methods == - `uniformTexture(uniform_name, texture)` - Sets a sampler uniform - `texture` should be a `RageTexture` object, obtainable with `:GetTexture()` on another actor - `uniformMatrix4fv(uniform_name, matrix)` - Sets a 4x4 matrix uniform, or an array of 4x4 matrix uniforms - `matrix` should be a Lua table with 16 elements (or any multiple of 16 for setting arrays) - `uniformMatrix3fv(uniform_name, matrix)` - Sets a 3x3 matrix uniform, or an array of 4x4 matrix uniforms - `matrix` should be a Lua table with 9 elements (or any multiple of 9 for setting arrays) - `uniformMatrix2fv(uniform_name, matrix)` - Sets a 2x2 matrix uniform, or an array of 4x4 matrix uniforms - `matrix` should be a Lua table with 4 elements (or any multiple of 4 for setting arrays) - `uniform4fv(uniform_name, value)` - Sets a *vec4 uniform, or an array of *vec4 uniforms - `value` should be a Lua table with 4 elements (or any multiple of 4 for setting arrays) - `uniform4f(uniform_name, x, y, z, w)` - Sets a *vec4 uniform - `uniform3fv(uniform_name, value)` - Sets a *vec3 uniform, or an array of *vec3 uniforms - `value` should be a Lua table with 3 elements (or any multiple of 3 for setting arrays) - `uniform3f(uniform_name, x, y, z)` - Sets a *vec3 uniform - `uniform2fv(uniform_name, value)` - Sets a *vec2 uniform, or an array of *vec2 uniforms - `value` should be a Lua table with 2 elements (or any multiple of 2 for setting arrays) - `uniform2f(uniform_name, x, y)` - Sets a *vec2 uniform - `uniform1fv(uniform_name, value)` - Sets a float uniform, or an array of float uniforms - `value` should be a Lua table with 1 element (or any multiple of 1 for setting arrays) - `uniform1f(uniform_name, value)` - Sets a float uniform - `uniform1iv(uniform_name, value)` - Sets an int/bool uniform, or an array of int/bool uniforms - `value` should be a Lua table with 1 element (or any multiple of 1 for setting arrays) - `uniform1i(uniform_name, value)` - Sets an int/bool uniform - `clearDefine(key)` - Removes a `#define` previously set by `shader:define(key, value)` - `define(key, value)` - Seems to add a `#define key value` line to the top of shaders to be compiled - Since it seems to just inject a line at the top of the shader code, you can't add a `#version ???` directive since the compiler will complain that the directive is no-longer the first directive in the code - This only affects shaders compiled in the future, so it won't work with shaders you specified Vert= / Frag= in the XML - `key` and `value` should be strings - See `shader:compile()` - `compileImmediate(a_string, a_string2)` - Not entirely sure what this does - I can only imagine a_string and a_string2 are supposed to be vert and frag shader code, but it's not seeming to want to attempt compiling code when I test this in an InitCommand - `compile(vert_code, frag_code)` - Seems to compile and link a GLSL shader program - `vert_code` and `frag_code` should be strings - Uses defines set with `shader:define(key, value)` - Parameters can be left as empty strings if you want to use the default NotITG shader code == How the heck did I find these? == Take a stringdump of the exe... no seriously. I wanted to upload matrices to the GPU in one of my WIP stepfiles (because screw dealing with transforming the world to make a camera and screw dealing with the tiny camera far clip plane - EDIT: See the ActorFrame section) but couldn't find any examples how when searching through any of the stepfiles I had downloaded... So I searched through the exe with a command like... {{{sh strings NotITG-V4.0.1.exe | grep -A 30 -B 30 'uniformMatrix' -A 20 -B 20 }}} (This is assuming you're running a Unix-y OS, which is probably not true but eh) EDIT Ok so the Simply Love theme for NotITG 4 has a Lua console in it now: toggle it with `Ctrl-9`. You can type stuff like `RageShaderProgram` and it'll give you a table of methods and what not on that - nifty! = Arrow path splines = There's a text doc floating around which goes over splines (https://www.dropbox.com/s/7gpmdml8o3ghz5v/splines.txt?dl=0), though there's a few things I found unclear about it, so here's some addendums. I can't be bothered to pretty up everything here, go check out that doc if you want to see how to reset splines or change spline interpolation. Amother doc: https://cdn.discordapp.com/attachments/227819834480656384/694707212882542692/splines.txt - `offset` - The text file documents `offset` as the "distance from recep in beats". Weeelll... that's not quite right. - To calculate an offset, given a number of beats, you do `beats_away * 100 * xmod_speed` - So for example, `8` beats away with a speed of `0.7x` would be `8 * 100 * 0.7` which equals an offset of `560` == Player methods == A player can be obtained as such: `local p1 = SCREENMAN:GetTopScreen():GetChild('PlayerP1')` - `SetXSpline(index, column, value, offset, activation_speed)` - Set an X position spline point - A `value` of 100 corresponds to the size of an arrow (64 pixels by default) - `index`: An integer from 0 - 39 (You can have up to 40 spline points per column) - `column`: Which column to apply the spline to (or `-1` for all columns) - `value`: What value you want to set this spline point to - `offset`: How far away arrows will be when hitting this spline point (see `offset` above) - `activation_speed`: How quickly spline changes should take effect (`-1` for instant) - `SetYSpline(index, column, value, offset, activation_speed)` - Set a Y position spline point - A `value` of 100 corresponds to the size of an arrow (64 pixels by default) - `SetZSpline(index, column, value, offset, activation_speed)` - Set a Z position spline point - A `value` of 100 corresponds to the size of an arrow (64 pixels by default) - `SetRotXSpline(index, column, value, offset, activation_speed)` - Set an X rotation spline point - `value` is in radians, multiplied by 100 (so a value of `628.3` equals 360deg) - `SetRotYSpline(index, column, value, offset, activation_speed)` - Set a Y rotation spline point - `value` is in radians, multiplied by 100 (so a value of `628.3` equals 360deg) - `SetRotZSpline(index, column, value, offset, activation_speed)` - Set a Z rotation spline point - `value` is in radians, multiplied by 100 (so a value of `628.3` equals 360deg) - `SetSizeSpline(index, column, value, offset, activation_speed)` - Set a size spline point - `value` works like the mini modifier (`100` makes the arrows half size, `200` makes then zero sized, negative makes them larger) - `SetStealthSpline(index, column, value, offset, activation_speed)` - Set a stealth spline point - `value` works like the Stealth modifier - `SetSkewSpline(index, column, value, offset, activation_speed)` - Set a skew spline point = Path, arrow, and stealth gradients = Never used these yet, here's a doc: https://www.dropbox.com/s/t1trfks2xyckwzh/gradients.txt?dl=0 = Hide the default UI = {{{lua function hide_default_ui() SCREENMAN:GetTopScreen():GetChild("Overlay"):hidden(1) SCREENMAN:GetTopScreen():GetChild("Underlay"):hidden(1) local players = {} table.insert(players, SCREENMAN:GetTopScreen():GetChild("PlayerP1")) table.insert(players, SCREENMAN:GetTopScreen():GetChild("PlayerP2")) for i, v in pairs(players) do if v ~= nil then SCREENMAN:GetTopScreen():GetChild("LifeP" .. i):hidden(1) SCREENMAN:GetTopScreen():GetChild("ScoreP" .. i):hidden(1) end end end }}} If you don't like it when songs disable the health and score UI elements, you can prevent them from disabling those by editing `Data/NotITGPrefs.ini`. {{{ini AlwaysShowLifeAndScore=1 }}} `Ctrl-L` also toggles the lifebar for one round also = Mods = There's a couple lists of mods - https://sm.heysora.net/itg.txt - https://sm.heysora.net/notitg.txt and I'll just note down what I find as I figure out what they do - Dark - Hides the receptors, though they still flash blue/yellow/green/etc. when you tap on a note - Sudden - Makes arrows appear on the notefield closer to the receptors than usual - SuddenOffset - Toy around with different percentage values to adjust how far away arrows appear with the Sudden mod - Stealth - Flashes arrows white and hides them as they approach the receptors - StealthPastReceptors - If you have Stealth enabled (or a stealth spline), by default arrows that aren't hit will appear again once they fly past the receptors - this makes them not do that - Beat - Makes the arrows/receptors shake on beats - Mini - Makes the playfield larger or smaller - 100% Mini = 0.5x scale - 200% Mini = 0.0x scale - Negative Mini makes arrows larger - Centered - Moves the receptors to the center of the screen, vertically - A mod value of over `100%` can be used to move the receptors past the center of the screen - ZBuffer - Makes it so arrow models read from/write to the depth buffer (which typically only happens when the Bumpy mod is on) == How mod strings work == Mod strings in this game are in the format `*speed value% mod_name` (do note, not all mods use the `%` sign though, but most do). Eg: `*2 200% Beat` will activate the `Beat` mod, with `200%` intensity, and it will interpolate towards 200% intensity at a speed or `2`...whatever that means. `*speed` and `value%` can be omitted if you want to use default values. A speed of `-1` can be used to activate a mod instantly. = 3D models = NotITG uses Milkshape 3D ASCII files to store 3D models. If you've no idea how to make those, or otherwise don't want to deal with Milkshape, I don't blame ya! Thankfully FMS_Cat made a tool to convert OBJ files to Milkshape ASCII files. https://github.com/FMS-Cat/obj2ms3dascii Anyways, you can add a model to your XML with the `File` attribute {{{xml }}} One other note about 3D models (that certainly drove me crazy for a little bit): the NotITG Lua docs on heysora.net say that the Z buffer is used by default for 3D models. If you're working in a `#BGCHANGES` bit, it's not! So you may want to toss in a `self:SetUseZBuffer(true)` call in your model OnCommands.....or, y'know, you should probably just be using `#BETTERBGCHANGES` instead. = ActorFrame = Y'know when I said earier that I the far clipping plane was too short... apparently `FarDist` is an XML attribute you can put on an `ActorFrame` - `FOV` too (though that one is easy enough to set from Lua anyways). %% vim: set ft=vimwiki: