Διόρθωση σύγκλισης των προβολέων με χρήση Pixel Shaders!

dimitris__

AVClub Addicted Member
23 November 2007
2,013
Γλυκά Νερά Αττικής
Το θέμα της σύγκλισης των panel των τρίτσιπων προβολέων απασχολεί λίγο πολύ όλους τους κατόχους τους, αφού η τέλεια σύγκλιση των τριών panel (κόκκινου (R), πράσινου (G) και μπλέ (Β)) απλά δεν υπάρχει. Συνήθως δεν χρειάζεται να πάει κάποιος πολύ κοντά στην οθόνη για να διαπιστώσει πράσινες, κόκκινες ή μπλέ "σκιές" στα περιγράμματα. Ο δικός μου προβολέας έχει 1-1,5 pixel απόκλιση του κόκκινου προς τα πάνω.

Οι pixel shaders (PS) είναι προγράμματα που μιλούν στην κάρτα γραφικών και κανονίζουν χαρακτηριστικά των pixels, όπως το χρώμα, τη διαφάνεια, τον φωτισμό κλπ. Οπότε χρησιμοποιώντας έναν PS θα μπορούσα θεωρητικά να "μετακινήσω" το κόκκινο panel προς τα κάτω ώστε να επιτύχω την τέλεια σύγκλιση.

Έψαχνα καιρό να βρώ την καλύτερη λύση για το πρόβλημα αυτό, και τη βρήκα στο forum του Doom9 και συγκεκριμένα από τον απίστευτο Jan-Willem ο οποίος είναι Ο Mάγος των Pixel Shaders! Είχε ήδη γράψει αρκετούς τους οποίους και μοιράζεται με τα μέλη του Doom9. Αφού είδα τη δουλειά του, του περιέγραψα το πρόβλημά μου και μετά από λίγες ώρες μου είχε έτοιμους τους PS που ήθελα! Απίστευτος;

Οι pixel shaders που μου έστειλε, όχι μόνο "μετακινούν τα panels" με ακρίβεια μικρότερη του ενός pixel, αλλά ρυθμίζουν και άλλες παραμέτρους όπως το "Παραλληλόγραμμο" και το "Keystone" που βοηθάει σε περιπτώσεις που η απόκλιση δεν είναι η ίδια σε όλη την οθόνη!

Αφού πειραματίστηκα αρκετά, τράβηξα μερικές κοντινές (με macro) φωτογραφίες για να σας δείξω τη βελτίωση:

img0975gq.jpg
img0976k.jpg


img0981d.jpg

img0982z.jpg

img0983vy.jpg

img0984sn.jpg


Η διαδικασία για την χρήση ενός PS είναι η εξής:

Στον Media Player Classic Homecinema κάνουμε δεξί κλίκ -> Shaders -> Edit
Στο πάνω αριστερά κουτάκι δίνουμε ένα όνομα για τον PS. Στο δεξί επιλέγουμε τη version 3 (ps_3_0)
Στο κάτω κουτάκι βάζουμε τον κώδικα του shader.Είμαστε έτοιμοι!
Τώρα απομένει μόνο να σκαλίσουμε τις παραμέτρους του PS για να φέρουμε την εικόνα στα μέτρα μας. Υπάρχουν σχόλια στον κώδικα που εξηγούν τη λειτουργία.

Τι λέτε;
 
Last edited:

dimitris__

AVClub Addicted Member
23 November 2007
2,013
Γλυκά Νερά Αττικής
Να λοιπόν οι pixel shaders του απίστευτου Ολλανδού Jan-Willem Krans

Pixel shader για οριζόντιo panel alignment:


3LCD panel horizontal software alignment, Catmull-Rom spline6 interpolated

Code:
// (C) 2011 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program 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, version 2.
// This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// 3LCD panel horizontal software alignment, Catmull-Rom spline6 interpolated
// This shader should be run as a screen space pixel shader.
// This shader requires compiling with ps_2_a, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// If possible, avoid compiling with the software emulation modes (ps_?_sw). Pixel shaders require a lot of processing power to run in real-time software mode.
// This shader is meant to work with linear RGB input and output. Regular R'G'B' with a video gamma encoding will have to be converted with the linear gamma shaders to work properly.
// This shader can only work when the display device receives input in its native display resolution, with over- and underscan disabled. This is to facilitate 1:1 pixel mapping.
// This shader can perform software alignment by Catmull-Rom spline6 interpolation for a 3LCD projector's red and blue panels.

// fractions, either decimal or not, are allowed
// set the horizontal resolution
#define HorizontalResolution 1920.
// RedControls and BlueControls, 0 is disabled, 1 is enabled
#define RedControls 1
#define BlueControls 1
// RedShiftLeftToRight and BlueShiftLeftToRight, a value of 3. will shift three pixels to the right, 0 is disabled
#define RedShiftLeftToRight 64.
#define BlueShiftLeftToRight -64.
// RedScaleHorizontal and BlueScaleHorizontal, the centered horizontal magnification factor, a value of HorizontalResolution-3. will scale the output to 3 pixels larger, a value of HorizontalResolution means disabled
#define RedScaleHorizontal HorizontalResolution-128.
#define BlueScaleHorizontal HorizontalResolution+128.
// RedParallelogram and BlueParallelogram, the centered horizontal offset factor on the bottom, a value of 3. will shift 0 pixels to the left on the top, and 3 pixels to the left on the bottom, 0 is disabled
#define RedParallelogram 256.
#define BlueParallelogram -256.
// RedKeystone and BlueKeystone, the centered horizontal magnification factor on the bottom, a value of -3. will scale the output to 0 pixels larger on the top, and 3 pixels larger on the bottom, 0 is disabled
#define RedKeystone -192.
#define BlueKeystone 192.

sampler s0;
#define spR(a, o) float a = tex2D(s0, float2(coordR+o*fxR/HorizontalResolution, tex.y)).r;
#define spB(a, o) float a = tex2D(s0, float2(coordB+o*fxB/HorizontalResolution, tex.y)).b;

float4 main(float2 tex : TEXCOORD0) : COLOR
{
	float4 s1 = tex2D(s0, tex);// base pixel
#if RedControls == 1
	float coordR = (tex.x-.5)*(RedScaleHorizontal+tex.y*RedKeystone)+.5*HorizontalResolution-RedShiftLeftToRight+tex.y*RedParallelogram;// assign the output position, normalized to texture width in pixels
	float tR = frac(coordR);// calculate the difference between the output pixel and the original surrounding two pixels
	// adjust sampling matrix to put the ouput pixel in the interval [R2, R2+.5]
	float fxR;
	if(tR > .5) {coordR = (coordR-tR+1.5)/HorizontalResolution; tR = 1.-tR; fxR = -1;}
	else {coordR = (coordR-tR+.5)/HorizontalResolution; fxR = 1;}
	tR *= 4;// compensate for the two iterations

	spR(R0, -2) spR(R1, -1) spR(R2, 0) spR(R3, 1) spR(R4, 2)// original pixels
	if(tR <= 1) s1.r = (((R0*3/256.-R1*7/128.+R2*3/32.-R3*9/128.+R4*5/256.)*tR+R1*19/128.+R3*21/128.-R0*7/256.-R2/4.-R4*9/256.)*tR+(R3-R1)*21/128.+(R0-R4)*5/256.)*tR+R2;// insert interpolated value for the interval [R2, R2+.25]
	else {
		spR(R5, 3)// sample an additional pixel
		tR -= 1.;
		s1.r = (((((R0+R4)*3+R2*26+R5-R1*15-R3*18)*tR+R1*35+R3*30-R0*5-R2*58-R4-R5)*tR+R3*144-(R1+R4)*16-R2*112)*tR+R0*2+R2*432+R3*132-R1*36-R4*18)/512.;}// insert interpolated value for the interval (R2+.25, R2+.5]
#endif
#if BlueControls == 1
	float coordB = (tex.x-.5)*(BlueScaleHorizontal+tex.y*BlueKeystone)+.5*HorizontalResolution-BlueShiftLeftToRight+tex.y*BlueParallelogram;// assign the output position, normalized to texture width in pixels
	float tB = frac(coordB);// calculate the difference between the output pixel and the original surrounding two pixels
	// adjust sampling matrix to put the ouput pixel in the interval [B2, B2+.5]
	float fxB;
	if(tB > .5) {coordB = (coordB-tB+1.5)/HorizontalResolution; tB = 1.-tB; fxB = -1;}
	else {coordB = (coordB-tB+.5)/HorizontalResolution; fxB = 1;}
	tB *= 4;// compensate for the two iterations

	spB(B0, -2) spB(B1, -1) spB(B2, 0) spB(B3, 1) spB(B4, 2)// original pixels
	if(tB <= 1) s1.b = (((B0*3/256.-B1*7/128.+B2*3/32.-B3*9/128.+B4*5/256.)*tB+B1*19/128.+B3*21/128.-B0*7/256.-B2/4.-B4*9/256.)*tB+(B3-B1)*21/128.+(B0-B4)*5/256.)*tB+B2;// insert interpolated value for the interval [B2, B2+.25]
	else {
		spB(B5, 3)// sample an additional pixel
		tB -= 1.;
		s1.b = (((((B0+B4)*3+B2*26+B5-B1*15-B3*18)*tB+B1*35+B3*30-B0*5-B2*58-B4-B5)*tB+B3*144-(B1+B4)*16-B2*112)*tB+B0*2+B2*432+B3*132-B1*36-B4*18)/512.;}// insert interpolated value for the interval (B2+.25, B2+.5]
#endif
	return s1;
}





Pixel shader για κάθετο panel alignment:


3LCD panel vertical software alignment, Catmull-Rom spline6 interpolated

Code:
// (C) 2011 Jan-Willem Krans (janwillem32 <at> hotmail.com)
// This file is part of Video pixel shader pack.
// This program 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, version 2.
// This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// 3LCD panel vertical software alignment, Catmull-Rom spline6 interpolated
// This shader should be run as a screen space pixel shader.
// This shader requires compiling with ps_2_a, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports.
// If possible, avoid compiling with the software emulation modes (ps_?_sw). Pixel shaders require a lot of processing power to run in real-time software mode.
// This shader is meant to work with linear RGB input and output. Regular R'G'B' with a video gamma encoding will have to be converted with the linear gamma shaders to work properly.
// This shader can only work when the display device receives input in its native display resolution, with over- and underscan disabled. This is to facilitate 1:1 pixel mapping.
// This shader can perform vertical software alignment by Catmull-Rom spline6 interpolation for a 3LCD projector's red and blue panels.

// fractions, either decimal or not, are allowed
// set the vertical resolution
#define VerticalResolution 1080.
// RedControls and BlueControls, 0 is disabled, 1 is enabled
#define RedControls 1
#define BlueControls 1
// RedShiftTopToBottom and BlueShiftTopToBottom, a value of 3. will shift three pixels to the bottom, 0 is disabled
#define RedShiftTopToBottom 64.
#define BlueShiftTopToBottom -64.
// RedScaleVertical and BlueScaleVertical, the centered vertical magnification factor, a value of VerticalResolution-3. will scale the output to 3 pixels larger, a value of VerticalResolution means disabled
#define RedScaleVertical VerticalResolution-128.
#define BlueScaleVertical VerticalResolution+128.
// RedParallelogram and BlueParallelogram, the centered vertical offset factor on the right, a value of 3. will shift 0 pixels to the top on the left, and 3 pixels to the top on the right, 0 is disabled
#define RedParallelogram 256.
#define BlueParallelogram -256.
// RedKeystone and BlueKeystone, the centered vertical magnification factor on the right, a value of -3. will scale the output to 0 pixels larger on the left, and 3 pixels larger on the right, 0 is disabled
#define RedKeystone -192.
#define BlueKeystone 192.

sampler s0;
#define spR(a, o) float a = tex2D(s0, float2(tex.x, coordR+o*fyR/VerticalResolution)).r;
#define spB(a, o) float a = tex2D(s0, float2(tex.x, coordB+o*fyB/VerticalResolution)).b;

float4 main(float2 tex : TEXCOORD0) : COLOR
{
	float4 s1 = tex2D(s0, tex);// base pixel
#if RedControls == 1
	float coordR = (tex.y-.5)*(RedScaleVertical+tex.x*RedKeystone)+.5*VerticalResolution-RedShiftTopToBottom+tex.x*RedParallelogram;// assign the output position, normalized to texture width in pixels
	float tR = frac(coordR);// calculate the difference between the output pixel and the original surrounding two pixels
	// adjust sampling matrix to put the ouput pixel in the interval [R2, R2+.5]
	float fyR;
	if(tR > .5) {coordR = (coordR-tR+1.5)/VerticalResolution; tR = 1.-tR; fyR = -1;}
	else {coordR = (coordR-tR+.5)/VerticalResolution; fyR = 1;}
	tR *= 4;// compensate for the two iterations

	spR(R0, -2) spR(R1, -1) spR(R2, 0) spR(R3, 1) spR(R4, 2)// original pixels
	if(tR <= 1) s1.r = (((R0*3/256.-R1*7/128.+R2*3/32.-R3*9/128.+R4*5/256.)*tR+R1*19/128.+R3*21/128.-R0*7/256.-R2/4.-R4*9/256.)*tR+(R3-R1)*21/128.+(R0-R4)*5/256.)*tR+R2;// insert interpolated value for the interval [R2, R2+.25]
	else {
		spR(R5, 3)// sample an additional pixel
		tR -= 1.;
		s1.r = (((((R0+R4)*3+R2*26+R5-R1*15-R3*18)*tR+R1*35+R3*30-R0*5-R2*58-R4-R5)*tR+R3*144-(R1+R4)*16-R2*112)*tR+R0*2+R2*432+R3*132-R1*36-R4*18)/512.;}// insert interpolated value for the interval (R2+.25, R2+.5]
#endif
#if BlueControls == 1
	float coordB = (tex.y-.5)*(BlueScaleVertical+tex.x*BlueKeystone)+.5*VerticalResolution-BlueShiftTopToBottom+tex.x*BlueParallelogram;// assign the output position, normalized to texture width in pixels
	float tB = frac(coordB);// calculate the difference between the output pixel and the original surrounding two pixels
	// adjust sampling matrix to put the ouput pixel in the interval [B2, B2+.5]
	float fyB;
	if(tB > .5) {coordB = (coordB-tB+1.5)/VerticalResolution; tB = 1.-tB; fyB = -1;}
	else {coordB = (coordB-tB+.5)/VerticalResolution; fyB = 1;}
	tB *= 4;// compensate for the two iterations

	spB(B0, -2) spB(B1, -1) spB(B2, 0) spB(B3, 1) spB(B4, 2)// original pixels
	if(tB <= 1) s1.b = (((B0*3/256.-B1*7/128.+B2*3/32.-B3*9/128.+B4*5/256.)*tB+B1*19/128.+B3*21/128.-B0*7/256.-B2/4.-B4*9/256.)*tB+(B3-B1)*21/128.+(B0-B4)*5/256.)*tB+B2;// insert interpolated value for the interval [B2, B2+.25]
	else {
		spB(B5, 3)// sample an additional pixel
		tB -= 1.;
		s1.b = (((((B0+B4)*3+B2*26+B5-B1*15-B3*18)*tB+B1*35+B3*30-B0*5-B2*58-B4-B5)*tB+B3*144-(B1+B4)*16-B2*112)*tB+B0*2+B2*432+B3*132-B1*36-B4*18)/512.;}// insert interpolated value for the interval (B2+.25, B2+.5]
#endif
	return s1;
}
 
Last edited:

george k.

Senior Member
14 April 2008
377
Καταρχήν συγχαρητήρια. Το θέμα το βρίσκω εκπληκτικά ενδιαφέρον.
Όντως βλέπω ότι το κόκκινο ήρθε, αλλά το μπλέ είναι off. Επίσης δουλεύουν οι shaders με madVR;
 
4 October 2006
56
Προφανως οι PS που ζητησε ηταν για την αποσυγκλιση του κοκκινου εικονοστοιχειου. Αν εφαρμοσει τον αναλογο PS και για το μπλε, θα ερθει στα ισα του... Αλλο με απασχολει εμενα. Η εφαρμογη ενος PS μπλεκεται με την μηχανη γραφικων και με τον scaler του προβολεα. Υπαρχει καποια διαφορα στην ευκρινεια ή στην αποδοση της κινησης?
 

dimitris__

AVClub Addicted Member
23 November 2007
2,013
Γλυκά Νερά Αττικής
Η διάχυση του μπλέ είναι ένα θέμα του LG AF-115 που όμως δεν οφείλεται στη σύγκλιση των panels. Είναι "της μάνας του". Βέβαια οι φωτογραφίες είναι τραβηγμένες από τους 20 πόντους απόσταση και το πρόβλημα φαίνεται μεγενθυμένο, δεν είναι ενοχλητικό σε normal απόσταση (3,5m σε 120'' που κάθομαι εγώ).

Όσον αφορά στους συγκεκριμένους pixel shaders δεν αφορούν μόνο το κόκκινο, αλλά και τα τρία χρώματα. Βασικά έχοντας σαν "σταθερό panel" το πράσινο μετακινούμε τα κόκκινο και μπλέ κατα βούληση ώστε να τα "καπακώσουμε" με απόλυτη ακρίβεια.

Ο πρώτος pixel shader "κινεί τα πανελ" στον άξονα "Ψ" ενώ ο δεύτερος στον "X". Οι PS αυτοί δεν είναι "fix" αλλά μπορούμε φυσικά να τους προσαρμόσουμε στις ανάγκες του δικού μας projector. Τα controls που έχουμε πάνω στον 1ο shader (και ευθέως ανάλογα στον δεύτερο) είναι:

// fractions, either decimal or not, are allowed
// set the horizontal resolution
#define HorizontalResolution 1920. (εδώ ορίζουμε την οριζόντια ανάλυση)
// RedControls and BlueControls, 0 is disabled, 1 is enabled
#define RedControls 1 Εδώ ενεργοποιούμε ή απενεργοποιούμε συνολικά τα ρυθμιστικά του Κόκκινου
#define BlueControls 1 Εδώ ενεργοποιούμε ή απενεργοποιούμε συνολικά τα ρυθμιστικά του Μπλέ
// RedShiftLeftToRight and BlueShiftLeftToRight, a value of 3. will shift three pixels to the right, 0 is disabled
#define RedShiftLeftToRight 1.7. Εδώ μετακινούμε το Κόκκινο panel (στο παράδειγμα είναι 1.7 pixels προς τα δεξιά)
#define BlueShiftLeftToRight -0.Εδώ μετακινούμε το Μπλέ panel (στο παράδειγμα είναι 0 pixels, αν δηλαδή δεν έχουμε πρόβλημα)
// RedScaleHorizontal and BlueScaleHorizontal, the centered horizontal magnification factor, a value of HorizontalResolution-3. will scale the output to 3 pixels larger, a value of HorizontalResolution means disabled
#define RedScaleHorizontal HorizontalResolution0. Εδώ μπορούμε να μεγενθύνουμε το Κόκκινο panel (κάτι που δέν χρειάζεται συνήθως), οπότε το έβαλα 0
#define BlueScaleHorizontal HorizontalResolution0. Εδώ μπορούμε να μεγενθύνουμε το Μπλέ panel (κάτι που δέν χρειάζεται συνήθως), οπότε το έβαλα 0
// RedParallelogram and BlueParallelogram, the centered horizontal offset factor on the bottom, a value of 3. will shift 0 pixels to the left on the top, and 3 pixels to the left on the bottom, 0 is disabled
#define RedParallelogram 1. Εδώ ρυθμίζουμε το παραλληλόγραμμο του Κόκκινου (βοηθάει αν το πρόβλημα της σύγκλισης δεν είναι ομοιογενές σε όλη την οθόνη)
#define BlueParallelogram 0. Εδώ ρυθμίζουμε το παραλληλόγραμμο του Μπλέ (βοηθάει αν το πρόβλημα της σύγκλισης δεν είναι ομοιογενές σε όλη την οθόνη)
// RedKeystone and BlueKeystone, the centered horizontal magnification factor on the bottom, a value of -3. will scale the output to 0 pixels larger on the top, and 3 pixels larger on the bottom, 0 is disabled
#define RedKeystone 0. Αναλόγως και για το "Keystone"
#define BlueKeystone 0.Αναλόγως και για το "Keystone"
 

dimitris__

AVClub Addicted Member
23 November 2007
2,013
Γλυκά Νερά Αττικής
Απάντηση: Re: Διόρθωση σύγκλισης των προβολέων με χρήση Pixel Shaders!

Προφανως οι PS που ζητησε ηταν για την αποσυγκλιση του κοκκινου εικονοστοιχειου. Αν εφαρμοσει τον αναλογο PS και για το μπλε, θα ερθει στα ισα του... Αλλο με απασχολει εμενα. Η εφαρμογη ενος PS μπλεκεται με την μηχανη γραφικων και με τον scaler του προβολεα. Υπαρχει καποια διαφορα στην ευκρινεια ή στην αποδοση της κινησης?

Η ευκρίνεια βελτιώνεται (θεαματικά μάλιστα αν υπάρχει πρόβλημα σύγκλισης)
Η κίνηση δεν επηρρεάζεται
Ο scaler του προβολέα δεν έχει συμμετοχή. Όλα γίνονται με τους shaders της κάρτας γραφικών. Βέβαια ο συνδυασμός πολλών shaders μαζί ίσως να επηρρεάσει τον φόρτο μιας αδύναμης κάρτας γραφικών (π.χ. μιας onboard)
 

dimitris__

AVClub Addicted Member
23 November 2007
2,013
Γλυκά Νερά Αττικής
Απάντηση: Re: Διόρθωση σύγκλισης των προβολέων με χρήση Pixel Shaders!

Καταρχήν συγχαρητήρια. Το θέμα το βρίσκω εκπληκτικά ενδιαφέρον.
Όντως βλέπω ότι το κόκκινο ήρθε, αλλά το μπλέ είναι off. Επίσης δουλεύουν οι shaders με madVR;

Δεν έχω δοκιμάσει με madVR αλλά δεν βλέπω το λόγο να μην παίζει. Αν παίζουν οι άλλοι shaders που είναι ενσωματωμένοι στον MPC-HC (π.χ. ο sharpen) θα παίζουν και αυτοί που συζητάμε!
 

Portioli

Supreme Member
3 June 2007
3,942
Dystopia
Απάντηση: Re: Διόρθωση σύγκλισης των προβολέων με χρήση Pixel Shaders!

Δεν έχω δοκιμάσει με madVR αλλά δεν βλέπω το λόγο να μην παίζει. Αν παίζουν οι άλλοι shaders που είναι ενσωματωμένοι στον MPC-HC (π.χ. ο sharpen) θα παίζουν και αυτοί που συζητάμε!

δυστυχώς ο madvr δεν υποστηριζει τους shaders του Mpc-HC.
Eχει επιλογές να βαλεις μόνος σου scalers (oπως ο Ολλανδός έβαλε τον Catmull-Rom) αλλα οχι για custom διορθώσεις για gamut και gamma αναλόγως το προβολικό μέσο. Ο μονος τρόπος ειναι να περάσεις δικό σου αρχείο .3dlut μέσω του yCMS (color management system) στον ΜadVR .Το ολο εγχειρημα είχε ξεκινήσει πριν πολλα χρόνια στο AVS απο τον yesgrey Color Correction with an ΗTPC Το είχα παρατήσει αυτό το κόλπο γιατί δεν έχω colormeter. Δυστυχώς δεν μπορώ να βοηθήσω καθόλου. Οποιος έχει χρόνο και υπομονη ας ρίξει μια ματια και ας βοηθησει και τους υπόλοιπους.