laurentlb / shader-minifier

Minify and obfuscate GLSL or HLSL code
https://ctrl-alt-test.fr/minifier/
Apache License 2.0
424 stars 29 forks source link

I really liked this project, but struggling to use in a bundler #419

Closed VanderSP closed 1 month ago

VanderSP commented 1 month ago

Hi! I was searching for something nice to obfuscate optimize my shaders in bundle, then this project is the only one that´s clever!

I losing entire day trying to make a plugin with gpt help, it´s a mess... i ran the cli, read the glsl in text way (because js looked like non es6 but, maybe using some fileloader?), then i read the glsl minified in text, inject in a js template, spit out, erase temp glsl... and even this way, i would not know how to watch glsl files being changed, i always work in build watch mode... also i tried to hook in on beforeCompile so i can import the result... im quite tired and lost, so im writing for you save me!

thanks in advance

VanderSP commented 1 month ago

i got it working direclty from glsl, when i used preserve externals, i think only think i need now, is glsl trigger watch

laurentlb commented 1 month ago

because js looked like non es6

What's the issue? Did get an error when using the JS output?

VanderSP commented 1 month ago

the js contains some vars, but theres no exports, so i thought u made it for use require instead import... but i think if i have a es6 js output all would work fine, like watch

laurentlb commented 1 month ago

What change would you need in the file?

If you replace var with export const, it works?

VanderSP commented 1 month ago

well, it works, but this would require you changing stuff, and still i would ran in the issue i can´t watch the glsl source files...

const { execSync } = require('child_process')
const fs = require('fs')
const path = require('path')

class ShaderMinifierPlugin {
  constructor(options) {
    this.options = options || {}
    this.initialRun = true
  }

  apply(compiler) {
    compiler.hooks.beforeCompile.tap('ShaderMinifierPlugin', () => {
      // Skip if it's not the initial run or if it's not a production build
      if (!this.initialRun || process.env.NODE_ENV !== 'production') {
        return
      }

      const shaderDirectories = [
        path.resolve(__dirname, 'src', 'View', 'Shaders', 'Transitions')
      ]
      const outputDir = path.resolve(__dirname, 'src', 'View', 'Shaders', 'Minified', 'Transitions')
      const shaderExtensions = ['.glsl']
      const outputExtension = '.js'  // Assuming the minifier outputs .js files

      this.initialRun = false

      // Ensure the output directory exists
      if (!fs.existsSync(outputDir)) {
        fs.mkdirSync(outputDir, { recursive: true })
      }

      shaderDirectories.forEach(shaderDir => {
        const shaderFiles = fs.readdirSync(shaderDir).filter(file => {
          return shaderExtensions.includes(path.extname(file))
        })

        shaderFiles.forEach(file => {
          const inputFilePath = path.join(shaderDir, file)
          const outputFileName = path.basename(file, path.extname(file)) + outputExtension
          const outputFilePath = path.join(outputDir, outputFileName)
          try {
            execSync(`shader_minifier.exe --format js --preserve-externals ${inputFilePath} -o ${outputFilePath}`)
            console.log(`Successfully minified shader: ${file} to ${outputFileName}`)
          } catch (error) {
            console.error(`Error minifying shader: ${inputFilePath}`, error)
          }
        })
      })
    })
  }
}

module.exports = ShaderMinifierPlugin
laurentlb commented 1 month ago

Changing the output of Shader Minifier is a valid feature request. We can output something compatible with ES6 modules.

However, watching the files is the job of your build tool. I would encourage you to check with them (or on stackoverflow) if you need help with it.

VanderSP commented 1 month ago

Thanks for fast replies! i can import glsl via rawloader, but obviously es6 would be nice... also if possible omit _glsl at the end of names... but yes i must find a way to watch .glsl source files that feed the minifier... i found very frustrating to maybe need to use chokidar... im not deep bundler genius lol

VanderSP commented 1 month ago

Hey I`ve just got the best idea, can you please make it accept .js as input? like following same pattern of output:

Input is js with some export const glsl =

but about output, i can deal with glsl output, because via rawloader i can read it, so keeping glsl at output it will prevent a retrigger from bundler (BUT I CAN BE WRONG HERE) because i think the plugin hooking at beforeCompile would prevent that naturally (also enabling importing the recent minified file).

Thanks!

laurentlb commented 1 month ago

No, sorry. We can accept only shader files as input.

VanderSP commented 1 month ago

I think the best solution for me is still using raw loader with glsl file output, in text mode... just figure out how to watch glsl changes

VanderSP commented 1 month ago

with help of gpts, i created a big build script that does everything detailed in a way that works,

exec(shader_minifier.exe --format text --no-renaming --aggressive-inlining --preprocess ${inputFilePath} -o ${outputFilePath}, (error, stdout, stderr) => {

in simple shaders, i noted that --preserve-externals (maybe unform names?) is enough... but opted to norenaming, because in complex shader i dunno why breaked (tested preserve globals also same thing)...

enabled aggressive inlining but dont noted much agressiveness (i dont understand fully the concept maybe) enabled preprocess because sounds good, but dont know when it´s triggered :D

Thanks! (at least now no sniffers in the bundle!)