znw-test Posted November 28, 2022 Share Posted November 28, 2022 I usr [email protected] and Chrome. However, I found that the texture became very blurry when I zoomed out. The browser img tag, by contrast, is clear. I don't know if I didn't set something right. Can someone take a look at it for me? I use this Image as a sprite's texture. I set the width and height of the Sprite to 0.2 times the width and height of the texture. The results presented are vague. I wrote a demo and compared the img tag image with the same width and height, and the difference was even more obvious. Can someone tell me what makes such a difference? My development environment: Browser: Google Chrome 107.0.5304.110 System: MacOS 10.15.6 Code: <!-- https://codepen.io/znw-test/pen/oNyMvGg --> <script src="https://pixijs.download/v6.2.2/pixi.js"></script> <script> let canvasWidth = 1000 let canvasHeight = 800 const app = new PIXI.Application({ width: canvasWidth, height: canvasHeight, backgroundColor: 0x1099bb, }); document.body.appendChild(app.view); let scaleRatio = .2 let originTexture let mainSprite let img function init(o){ originTexture = o mainSprite = new PIXI.Sprite(originTexture) mainSprite.x = 0 mainSprite.y = 0; mainSprite.width = originTexture.width * scaleRatio; mainSprite.height = originTexture.height * scaleRatio; app.stage.addChild(mainSprite) } function changeFile(e){ let src = URL.createObjectURL(e[0]) let img = new Image() img.src=src let originTextureLoader = PIXI.Texture.fromLoader(src) originTextureLoader.then((o)=>{ URL.revokeObjectURL(src) img.style.width = (img.naturalWidth * scaleRatio) + 'px' img.style.height = (img.naturalHeight * scaleRatio) +'px' document.body.appendChild(img) originTexture && originTexture.destroy(true) mainSprite && mainSprite.destroy({children:true, texture:true, baseTexture:true}) originTextureLoader = null init(o) }) } </script> <div> <label> Select Image: <input type="file" onchange="changeFile(this.files)" /> </label> </div> Quote Link to comment Share on other sites More sharing options...
Alexander Kolosov Posted November 28, 2022 Share Posted November 28, 2022 Hi. I checked and I don't have such a problem. But I noticed that you use resolution: 2. Try to set: resolution: window.devicePixelRatio Quote Link to comment Share on other sites More sharing options...
znw-test Posted November 29, 2022 Author Share Posted November 29, 2022 (edited) 15 hours ago, Alexander Kolosov said: Hi. I checked and I don't have such a problem. But I noticed that you use resolution: 2. Try to set: resolution: window.devicePixelRatio Thank you for your reply. I have two screens, one with a devicePixelRatio of 1(1920 x 1080) and the other with a devicePixelRatio of 2(2880 x 1800).I only set the resolution of the application to 2 for both screens to work properly. I don't know why. I changed my demo. Added a renderTexture and a filter. The filters are set for the stage as the mouse moves into it. The resolution of the filter must be consistent with that of the application; otherwise, the image will be blurred.https://codepen.io/znw-test/full/oNyMvGg <script src="https://pixijs.download/v6.2.2/pixi.js"></script> <script> let canvasWidth = 1000 let canvasHeight = 800 const app = new PIXI.Application({ width: canvasWidth, height: canvasHeight, backgroundColor: 0x1099bb, resolution: 2, }); app.renderer.autoDensity = true app.renderer.resize(canvasWidth, canvasHeight) document.body.appendChild(app.view); let scaleRatio = 0.2 let filter = new PIXI.Filter(null, null) filter.resolution = 2; app.stage.filterArea = app.screen; app.stage.interactive = true app.stage.on('mouseover', ()=>{app.stage.filters = [filter]}) app.stage.on('mouseout', ()=>{app.stage.filters = null}) let originTexture let mainSprite let img let finalTexture let quadSprite const VERTEX_SHADER = ` attribute vec2 a_position; attribute vec2 a_texCoord; varying vec2 vTexcoord; void main() { gl_Position = vec4(a_position, 0, 1); vTexcoord = (a_texCoord); } ` const FRAGMENT_SHADER = ` precision highp float; uniform sampler2D uTexture; varying vec2 vTexcoord; void main() { highp vec4 color = texture2D(uTexture, vTexcoord); // gl_FragColor = vec4(vec3(1.0,1.0,1.0) - color.rgb, 1.0); gl_FragColor = color; } ` const geometry = new PIXI.Geometry() .addAttribute('a_position', // the attribute name [-1, -1, // x, y 1, -1, // x, y 1, 1, -1, 1 ], // x, y 2) // the size of the attribute .addAttribute('a_texCoord', // the attribute name [0, 0, // u, v 1, 0, // u, v 1, 1, 0, 1 ], // u, v 2) // the size of the attribute .addIndex([0, 1, 2, 0, 2, 3]); const uniforms = { uTexture: PIXI.Texture.EMPTY }; const shader = PIXI.Shader.from(VERTEX_SHADER, FRAGMENT_SHADER, uniforms); const quad = new PIXI.Mesh(geometry, shader); function init(o) { originTexture = o uniforms.uTexture = originTexture finalTexture = PIXI.RenderTexture.create({ width: originTexture.width, height: originTexture.height }); quadSprite = new PIXI.Sprite(finalTexture) mainSprite = new PIXI.Sprite(originTexture) mainSprite.x = 0 mainSprite.y = 0 mainSprite.width = originTexture.baseTexture.realWidth * scaleRatio; mainSprite.height = originTexture.baseTexture.realHeight * scaleRatio; quadSprite.x = mainSprite.width quadSprite.y = 0 quadSprite.width = originTexture.baseTexture.realWidth * scaleRatio; quadSprite.height = originTexture.baseTexture.realHeight * scaleRatio; app.renderer.render(quad, { renderTexture: finalTexture }) console.log("can add") app.stage.addChild(mainSprite) app.stage.addChild(quadSprite) } function changeFile(e) { let src = URL.createObjectURL(e[0]) img && document.body.removeChild(img) img = new Image() img.src = src let originTextureLoader = PIXI.Texture.fromLoader(src, src, null, { scaleMode: 1, resolution: 1 }) originTextureLoader.then((o) => { img.style.width = img.naturalWidth * scaleRatio + 'px' img.style.height = img.naturalHeight * scaleRatio + 'px' document.body.appendChild(img) URL.revokeObjectURL(src) finalTexture && finalTexture.destroy(true) originTexture && originTexture.destroy(true) mainSprite && mainSprite.destroy({ children: true, texture: true, baseTexture: true }) quadSprite && quadSprite.destroy({ children: true, texture: true, baseTexture: true }) originTextureLoader = null init(o) }) } </script> <div> <label> Select Image: <input type="file" onchange="changeFile(this.files)" /> </label> </div> Edited November 29, 2022 by ZZZZZZZZZ Fix bug Quote Link to comment Share on other sites More sharing options...
Alexander Kolosov Posted November 29, 2022 Share Posted November 29, 2022 Hi. I had a problem with blurring when the mouse focused on the image only when filter.resolution and app.renderer.resolution values are different. In current https://codepen.io/znw-test/pen/oNyMvGg filter.resolution = 2 and app.renderer.resolution = 2 and it looks good. But if you set the filter.resolution = 1 then when you hover the mouse it will become blurry. Quote Link to comment Share on other sites More sharing options...
Alexander Kolosov Posted November 29, 2022 Share Posted November 29, 2022 I think you need to use window.devicepixelratio for renderer and filter resolution. If you use 2 monitors with different DPI, then after moving the browser to another monitor the window.devicePixelRation will be changed and you will be able to update the renderer and filter resolution. Below is a rough example of how you can do that. added: requestAnimationFrame(this.render.bind(this)); function render() { app.renderer.resolution = window.devicePixelRatio; filter.resolution = window.devicePixelRatio; requestAnimationFrame(this.render.bind(this)); } full code: <script src="https://pixijs.download/v6.2.2/pixi.js"></script> <script> let canvasWidth = 1000 let canvasHeight = 800 const app = new PIXI.Application({ width: canvasWidth, height: canvasHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio, }); app.renderer.autoDensity = true app.renderer.resize(canvasWidth, canvasHeight) document.body.appendChild(app.view); let scaleRatio = 0.2 let filter = new PIXI.Filter(null, null) filter.resolution = window.devicePixelRatio; app.stage.filterArea = app.screen; app.stage.interactive = true app.stage.on('mouseover', ()=>{app.stage.filters = [filter]}) app.stage.on('mouseout', ()=>{app.stage.filters = null}) let originTexture let mainSprite let img let finalTexture let quadSprite const VERTEX_SHADER = ` attribute vec2 a_position; attribute vec2 a_texCoord; varying vec2 vTexcoord; void main() { gl_Position = vec4(a_position, 0, 1); vTexcoord = (a_texCoord); } ` const FRAGMENT_SHADER = ` precision highp float; uniform sampler2D uTexture; varying vec2 vTexcoord; void main() { highp vec4 color = texture2D(uTexture, vTexcoord); // gl_FragColor = vec4(vec3(1.0,1.0,1.0) - color.rgb, 1.0); gl_FragColor = color; } ` const geometry = new PIXI.Geometry() .addAttribute('a_position', // the attribute name [-1, -1, // x, y 1, -1, // x, y 1, 1, -1, 1 ], // x, y 2) // the size of the attribute .addAttribute('a_texCoord', // the attribute name [0, 0, // u, v 1, 0, // u, v 1, 1, 0, 1 ], // u, v 2) // the size of the attribute .addIndex([0, 1, 2, 0, 2, 3]); const uniforms = { uTexture: PIXI.Texture.EMPTY }; const shader = PIXI.Shader.from(VERTEX_SHADER, FRAGMENT_SHADER, uniforms); const quad = new PIXI.Mesh(geometry, shader); function init(o) { originTexture = o uniforms.uTexture = originTexture finalTexture = PIXI.RenderTexture.create({ width: originTexture.width, height: originTexture.height }); quadSprite = new PIXI.Sprite(finalTexture) mainSprite = new PIXI.Sprite(originTexture) mainSprite.x = 0 mainSprite.y = 0 mainSprite.width = originTexture.baseTexture.realWidth * scaleRatio; mainSprite.height = originTexture.baseTexture.realHeight * scaleRatio; quadSprite.x = mainSprite.width quadSprite.y = 0 quadSprite.width = originTexture.baseTexture.realWidth * scaleRatio; quadSprite.height = originTexture.baseTexture.realHeight * scaleRatio; app.renderer.render(quad, { renderTexture: finalTexture }) console.log("can add") app.stage.addChild(mainSprite) app.stage.addChild(quadSprite) requestAnimationFrame(this.render.bind(this)); } function render() { app.renderer.resolution = window.devicePixelRatio; filter.resolution = window.devicePixelRatio; requestAnimationFrame(this.render.bind(this)); } function changeFile(e) { let src = URL.createObjectURL(e[0]) img && document.body.removeChild(img) img = new Image() img.src = src let originTextureLoader = PIXI.Texture.fromLoader(src, src, null, { scaleMode: 1, resolution: 1 }) originTextureLoader.then((o) => { img.style.width = img.naturalWidth * scaleRatio + 'px' img.style.height = img.naturalHeight * scaleRatio + 'px' document.body.appendChild(img) URL.revokeObjectURL(src) finalTexture && finalTexture.destroy(true) originTexture && originTexture.destroy(true) mainSprite && mainSprite.destroy({ children: true, texture: true, baseTexture: true }) quadSprite && quadSprite.destroy({ children: true, texture: true, baseTexture: true }) originTextureLoader = null init(o) }) } </script> <div> <label> Select Image: <input type="file" onchange="changeFile(this.files)" /> </label> </div> Quote Link to comment Share on other sites More sharing options...
znw-test Posted November 29, 2022 Author Share Posted November 29, 2022 (edited) 1 hour ago, Alexander Kolosov said: I think you need to use window.devicepixelratio for renderer and filter resolution. If you use 2 monitors with different DPI, then after moving the browser to another monitor the window.devicePixelRation will be changed and you will be able to update the renderer and filter resolution. Thank you for your reply. ========== update ======== requestAnimationFrame(this.render.bind(this)); function render() { app.renderer.resolution = window.devicePixelRatio; filter.resolution = window.devicePixelRatio; app.renderer.resize(canvasWidth, canvasHeight); // add this line requestAnimationFrame(this.render.bind(this)); } After add resize code, the picture1 and picture2 problem solved. But the picture3 problem remains. ========== original ======== But this switch has a strange effect. If I insert an image on a screen with devicePixelRatio 2 and drag it onto a screen with devicePixelRatio 1, the stage will shrink. Picture 1: App init on a screen with a devicePixelRatio of 2. Picture 2: Move the browser to a screen with a devicePixelRatio of 1. But if I refresh the page and insert an image on a screen with a devicePixelRatio of 1, the image appears blurry. See Picture 3. Picture 3: App init on a screen with a devicePixelRatio of 1. Edited November 29, 2022 by znw-test Additional Information Quote Link to comment Share on other sites More sharing options...
znw-test Posted November 29, 2022 Author Share Posted November 29, 2022 It seems that images render most like img tags when resolution is twice as big as devicePixelRadio. Why? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted December 1, 2022 Share Posted December 1, 2022 turn off mipmaps maybe? Quote Link to comment Share on other sites More sharing options...
znw-test Posted December 2, 2022 Author Share Posted December 2, 2022 6 hours ago, ivan.popelyshev said: turn off mipmaps maybe? Thank you for your reply. I tried to set MIPMAP_TEXTURES to OFF before instantiating the Application but it didn't seem to work out any better. PIXI.settings.MIPMAP_TEXTURES = PIXI.MIPMAP_MODES.OFF; const app = new PIXI.Application({ width: canvasWidth, height: canvasHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio, }); Quote Link to comment Share on other sites More sharing options...
jonforum Posted December 4, 2022 Share Posted December 4, 2022 On 12/1/2022 at 9:15 PM, znw-test said: Thank you for your reply. I tried to set MIPMAP_TEXTURES to OFF before instantiating the Application but it didn't seem to work out any better. PIXI.settings.MIPMAP_TEXTURES = PIXI.MIPMAP_MODES.OFF; const app = new PIXI.Application({ width: canvasWidth, height: canvasHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio, }); did you try remaster your img with contraint of POW2 ? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.